Skip to content
Latchkey LogoLatchkey home

No files were found with the provided path in upload-artifact

The message no files were found with the provided path is not a statement about your artifact, it is the result of a glob: actions/upload-artifact expanded its path input against the runner filesystem and got an empty list. Whether that ends the job, warns, or says nothing is decided by if-no-files-found, and the default lets the build stay green.

How the upload glob is resolved and what if-no-files-found does with an empty result
One sentence, three severities. The default is a warning, which is why this usually surfaces as a download failure in another job.

What this error means

The same sentence appears whether the step warned, failed or stayed silent, because all three branches emit identical text at different severities. The line below is the error one, from a run that had set if-no-files-found: error. At the shipped default the upload step is yellow rather than red, the job finishes, and the run looks fine. Minutes later a different job fails because the artifact it wanted is not there, and that is the failure people report. The line names an absolute path on the runner, which is worth reading carefully: it is the path the action resolved, not the one you typed.

Actions log, quoted from upload-artifact#810
##[error]No files were found with the provided path: /__w/_temp/release-assets. No artifacts will be uploaded.

A minimal workflow that produces it

This file is written for this page and has never been run. The build step changes directory and writes relative to the package it built, so the files land in packages/app/dist. The upload names dist, resolved against the workspace root, where nothing exists. Nothing in the run is red: the build passes, the upload warns, the artifact is absent.

.github/workflows/ci.yml (illustrative)
name: ci
on:
  push:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - run: npm ci && npm run build
        working-directory: packages/app
      - uses: actions/upload-artifact@v7
        with:
          name: site
          path: dist

Common causes

The build wrote to a different directory than the upload reads

The ordinary case, and the one the illustrative workflow shows. A working-directory on the build step, a build tool with its own output root, or a monorepo where each package writes into itself all put files where the upload path does not reach. The absolute path in the message is the whole diagnosis.

The step that should have produced the files did not run

A conditional step that evaluated false, a cached step that short-circuited, or a build that failed under continue-on-error all leave the directory empty. This looks identical in the log to a wrong path, which is why listing the directory before the upload is worth the two seconds.

Everything the pattern matched is a directory or a hidden file

Directories are filtered out of the match list, so a tree of empty directories uploads nothing. Hidden files have been excluded by default since version 4.4.0, so a path containing only dotfiles, a .next build that is being uploaded wholesale, or a coverage directory whose entries begin with a dot now matches zero files where it once matched many.

The path is right for a shell and wrong for an action

Tilde expansion, environment variables in shell syntax and relative paths borrowed from a run: block are the recurring near misses, because the action has its own handling for all three and it is not the shell one. In a container job the workspace is mapped as well, so even an absolute path can resolve differently between steps.

How to fix it

Make the empty match the failure

Do this first, before diagnosing anything. With if-no-files-found: error the run goes red on the step that has the path in front of it, rather than in a different job with a message about a missing artifact. On any upload a later job consumes, this is the default to write.

.github/workflows/ci.yml, corrected (illustrative)
      - uses: actions/upload-artifact@v7
        with:
          name: site
          path: packages/app/dist
          if-no-files-found: error

Print the directory from the same place the action will read it

The cheapest diagnostic is a listing taken from the workspace, which is where the action resolves a relative path. Doing it in the build step working directory proves nothing, because that is the frame the action does not use.

Terminal
ls -la "$GITHUB_WORKSPACE"
find "$GITHUB_WORKSPACE" -maxdepth 3 -name "dist" -type d

Include hidden files only when you mean to

If the files you expected begin with a dot, the exclusion added in version 4.4.0 is why they are missing. Turning it back on is one input, and it is worth narrowing the path at the same time: the reason for the change was that whole-directory uploads were carrying credentials out of a build, and re-enabling it over a broad path reinstates exactly that risk.

.github/workflows/ci.yml (illustrative)
      - uses: actions/upload-artifact@v7
        with:
          name: coverage
          path: packages/app/coverage/.tmp
          include-hidden-files: true
          if-no-files-found: error

Give multiple paths deliberately, and check the root

Several paths are allowed, one per line, with exclusions prefixed by an exclamation mark. With more than one the action recalculates the artifact root as their least common ancestor and logs that it has, so the layout inside the artifact changes. Read that line after adding a second path.

.github/workflows/ci.yml (illustrative)
      - uses: actions/upload-artifact@v7
        with:
          name: reports
          path: |
            packages/app/dist
            packages/app/coverage
            !packages/app/dist/**/*.map
          if-no-files-found: error

The same sentence at three severities

The action emits this text from a three-way switch on if-no-files-found, and the string is identical in all three branches. That is why a search for the message finds people describing it as a warning, as an error, and as something they never saw: one code path with a different reporting function on the end.

The default is warn, which the README documents as "Output a warning but do not fail the action". That default is why this error is nearly always discovered somewhere else: nothing fails, and the run holds one artifact fewer than it should until something tries to read it.

actions/upload-artifact, src/upload/upload-artifact.ts
case NoFileOptions.warn:
  core.warning(`No files were found with the provided path: ...`)
case NoFileOptions.error:
  core.setFailed(`No files were found with the provided path: ...`)
case NoFileOptions.ignore:
  core.info(`No files were found with the provided path: ...`)
if-no-files-foundHow the line is loggedWhat the job does
warn (the default)A warning annotationPasses, with no artifact
errorAn error annotationFails on the upload step
ignoreAn ordinary info linePasses, with nothing to notice

What the glob does and does not count

The search is a glob, and two of its rules produce an empty result that looks like it should not be. Directories are removed from the match list after globbing, so a pattern matching only an empty directory matches no files. Hidden files are excluded unless you ask for them, which changed in version 4.4.0: the release notes call it a breaking change made so credentials are not swept into an artifact by accident, and it is why a path holding only dotfiles now uploads nothing.

A third rule is about roots rather than matches. One path makes its own search path the artifact root; several paths make the action calculate their least common ancestor and use that, which quietly changes the directory structure inside the artifact. That never causes an empty match, but it explains the near miss where the upload succeeds and the layout is not what the download expects.

Then there is the path itself. working-directory applies to run: steps and not to an action, so a relative path on the upload resolves from the workspace root whatever the build step did. In a container job it is stranger: the report quoted above shows one step listing the file at one absolute path and the upload, in the same job, reporting an empty match at a different absolute path for the same directory. That report is open, and the lesson is to make the path explicit rather than trust two steps to agree.

Why there is no recorded run on this page

There is no runner failure here to record. The glob returns an empty list deterministically for as long as the files are not where the pattern points, so a recorded log would show the same sentence this page already quotes and add nothing. There is nothing to repair either: a runner cannot invent a build output, and retrying produces the identical empty match. The workflows are illustrative.

How to prevent it

  • Write if-no-files-found: error on every upload that another job depends on.
  • Use workspace-relative paths in an action, and keep working-directory for run: steps.
  • List the output directory in the step before the upload while a workflow is new.
  • Name hidden files explicitly rather than re-enabling them across a whole build directory.

Frequently asked questions

Why does upload-artifact say no files were found when the files exist?
Because the path was resolved from somewhere else. A relative path on the action is resolved against the workspace root, and working-directory on an earlier run: step does not move it. Compare the absolute path printed in the message with a listing taken from GITHUB_WORKSPACE, not with what the build step saw.
Should if-no-files-found be warn or error?
Error, for any upload another job consumes. The shipped default is warn, which keeps the job green and no artifact, so the first red step is a download failure somewhere else entirely. Leave it at warn only for genuinely optional output, such as a debug bundle that is uploaded on failure and is not always produced.
Why did upload-artifact stop uploading my dotfiles?
Version 4.4.0 stopped including hidden files by default, and the release notes label it a breaking change made to reduce the risk of credentials being uploaded by accident. Set include-hidden-files: true to restore the old behavior, and narrow the path at the same time so you are not re-opening the problem the change was made to close.
Does an empty directory count as a file for upload-artifact?
No. The action globs, then removes every match that is a directory, so a pattern matching only empty directories produces an empty file list and this message. It is a common surprise when a build is expected to have written into a directory that was created by an earlier step and then never filled.

Related guides

References

A build that uploaded nothing still spent its minutes. Latchkey prices them at $0.0025 at 2 vCPU. Start free → 30-day trial · No credit card