GitHub Actions · intermediate

GitHub Actions artifact checklist

Operational playbook for diagnosing GitHub Actions jobs that cannot exchange build output through the artifacts mechanism. Treats artifacts as a contract between jobs (name, path, retention, permissions) rather than a passive upload, and sequences decisions from symptom to proof. Each step names the boundary being checked, the evidence that distinguishes competing causes, and the safe action conditional on that evidence.

The symptoms

  • A downstream job fails with "No artifacts were found matching the pattern" or "Artifact download failed" even though an upstream job appeared to finish successfully.
  • An upload step reports "Artifact name must be unique" or "Failed to CreateArtifact" while the workflow summary lists no matching upload entry.
  • A job that depends on a previous job's artifact receives an empty directory after download, or downloads only a subset of the expected files.
  • actions/upload-artifact and actions/download-artifact steps pass locally but time out, exceed size limits, or skip silently in CI, leaving the consuming job with no input.
  • Workflow run summary shows an artifact entry, but consuming jobs in later matrix legs or later steps see "Path not found" because the artifact is bound to a different run, ref, or workflow.

Likely causes

  • Mismatch between the artifact name declared at upload and the name queried at download, including whitespace, case differences, or multiple uploads reusing the same name in the same run.
  • Path scope error: the upload path resolves to an empty or non-existent directory because a checkout, build, or glob step did not populate the expected location before the upload step ran.
  • Cross-job download referencing artifacts that are only available within a single job, or referencing artifacts from a different workflow run, branch, or pull request than the one executing the consumer.
  • Permission or scope mismatch: the workflow lacks actions: read on the required scope, or the artifact retention window has expired before the consumer step runs.
  • Version drift between actions/upload-artifact and actions/download-artifact, especially mixing v3 and v4, which use incompatible artifact formats and namespacing rules.
  • Large or binary payloads exceeding default artifact size or count limits, causing silent truncation or upload failure that the runner logs as a generic error.

First ten minutes

  1. 01Open the failed workflow run and read the summary panel: confirm which job declared the upload and which job attempted the download, noting the job IDs and step order.
  2. 02Inspect the upload-artifact step log and record the exact artifact name string, the resolved path argument, and any "Creating artifact" or "Failed to CreateArtifact" lines, including exit codes.
  3. 03Inspect the download-artifact step log and record the pattern requested, whether it includes a name or a path filter, and whether the response lists zero, one, or multiple matched artifacts.
  4. 04Compare the workflow YAML for the producing job and consuming job side by side, focusing on the actions/upload-artifact and actions/download-artifact invocations: name, path, if conditions, and needs topology.
  5. 05Check the workflow run's permissions block and any repository or organization policies that restrict actions: read, write, or artifact scopes, since these gate whether the steps can complete.
  6. 06Decide the branch: if names match, paths resolve, and versions align, suspect retention, size, or scope; if names differ, stop and correct the name contract before changing anything else.

Evidence to collect

  • The literal artifact name strings on the producer and consumer sides, byte-for-byte, including any matrix interpolation that may inject unintended characters.
  • The resolved upload path inside the producing job's workspace, verified by an upstream ls or directory-listing step captured in the log.
  • The download step's pattern argument, whether it targets a single named artifact or a glob, and the resulting matched-artifact count reported by the runner.
  • Runner logs for actions/upload-artifact and actions/download-artifact versions, retention warnings, size warnings, and any rate-limit or quota notices.
  • The workflow's needs graph and if-condition expressions on each step, since conditional steps can silently skip the upload while the consumer still expects the artifact.
  • Repository or organization settings that affect artifact retention duration and per-run artifact count, which determine whether a previously successful upload is still available at download time.

Where to look

  • The workflow YAML file at the commit SHA that produced the failing run, focusing on the upload-artifact and download-artifact steps and their surrounding job boundaries.
  • The workflow run summary page, which lists declared artifacts and their sizes, and links each to the producing job and step.
  • The runner log for the producing job, searching for "CreateArtifact", "UploadArtifact", and the resolved path argument echoed by the action.
  • The runner log for the consuming job, searching for "DownloadArtifact", the requested pattern, and the matched-artifact count.
  • Repository Settings under Actions, and any organization-level policies that override artifact retention, default permissions, or allowed actions lists.
  • The actions/upload-artifact and actions/download-artifact release notes for the pinned versions, to confirm format and naming compatibility across major versions.

Diagnostic steps

  1. 01Confirm name parity: extract the upload step's name argument and the download step's name or pattern argument, then diff them character by character, including matrix expressions and environment substitutions.
  2. 02Confirm path resolution: in the producing job, locate the step immediately before upload-artifact that is expected to produce the files, and verify the path exists and is non-empty using a logged ls or pwd output.
  3. 03Confirm topology: verify that the consuming job declares needs: [producer-job] (directly or transitively) and that no parallelism, matrix, or strategy change reorders execution relative to the upload.
  4. 04Confirm version compatibility: check that upload and download use the same major version of the respective actions, since v3 and v4 artifacts are not interchangeable by default.
  5. 05Confirm permissions and scope: verify the workflow's permissions block grants the required read or write scope for artifact operations, and that no step-level if condition silently disables the upload.
  6. 06Confirm retention and size: review repository or organization artifact retention settings and per-run limits, and check the runner log for size or count warnings emitted before the failure.
  7. 07Confirm cross-run isolation: if the consumer targets artifacts from a prior run or a different ref, validate that the workflow syntax supports that reference and that the source run has not been garbage-collected.

Common mistakes

  • Hard-coding an artifact name on download that differs from the upload name because of a renamed variable, a refactor of a composite action, or a typo introduced during a copy-paste edit.
  • Assuming a matrix leg that failed still produces an artifact that other legs can consume, when the workflow only collects artifacts from successful legs or from a specific needs chain.
  • Mixing actions/upload-artifact and actions/download-artifact major versions across jobs in the same workflow, producing format-incompatible artifacts and silent skips.
  • Uploading from a path that depends on a checkout, cache, or build step that was skipped by an if condition, so the directory exists but is empty.
  • Downloading with a glob pattern that the runner interprets as a name filter rather than a path filter, or vice versa, because the artifact's internal file layout was assumed rather than verified.
  • Overlooking retention: relying on an artifact from a previous workflow run or a scheduled job that has aged past the repository or organization retention window.

Safe fixes

  • If the names do not match, align the upload and download name arguments exactly, using a shared variable or composite action so future renames stay synchronized; do not change the path yet.
  • If the upload path resolves empty, add an explicit ls or find step immediately before upload-artifact that logs the resolved path and a file count, then re-run; only adjust the path argument after confirming the directory is populated.
  • If major versions differ, pin both upload-artifact and download-artifact to the same major version across all jobs in the workflow, and re-run a single job to validate format compatibility before touching retention or permissions.
  • If the needs topology is wrong, add or correct the needs: entry on the consumer job so it cannot start until the producer's upload step has completed; do not rely on step-level ordering alone.
  • If retention is too short, raise the repository or organization artifact retention setting within policy limits, or pass an explicit retention-days argument on the upload step, and re-run to observe the new value in the runner log.
  • If permissions are restricted, add the minimal permissions block required by the workflow (for example, actions: read) and re-run with the same commit SHA to compare before and after behavior; do not widen permissions beyond what the step requires.

Prove the fix

  1. 01The producing job's runner log shows a "CreateArtifact" or equivalent success line that echoes the exact artifact name and a non-zero byte count, and the workflow summary lists the artifact with its declared size.
  2. 02The consuming job's runner log shows the download step matching exactly one artifact by name, with the expected directory layout under the runner workspace after download.
  3. 03A subsequent step in the consuming job successfully reads or processes a known file from the downloaded directory, demonstrating end-to-end data flow rather than a mere step-level green check.
  4. 04The workflow's needs graph in the run visualization shows the consumer job starting strictly after the producer job completes, with no skipped or cancelled states in between.
  5. 05Re-running the same workflow on the same commit SHA produces identical artifact sizes and matched counts, ruling out retention or flakiness as the proximate cause.

Prevention and next steps

  • Define artifact names as workflow-level variables or outputs from a single composite action, and reference them by variable in every upload and download step to eliminate drift.
  • Pin actions/upload-artifact and actions/download-artifact to explicit version tags across the entire workflow file, and review upgrades centrally rather than per job.
  • After each upload step, add a short verification step that lists the resolved path and a file count, so empty uploads fail loudly instead of producing empty downloads downstream.
  • Document the artifact contract (name, path, retention, consumer) in the workflow file as a comment block, and require a review whenever a consumer job is added or renamed.
  • Periodically audit repository and organization artifact retention settings against the longest expected gap between producing and consuming jobs, especially for scheduled or nightly workflows.

Safe commands and checks

gh run view <run-id> --json jobs,steps --jq '.jobs[] | {name: .name, conclusion: .conclusion, steps: [.steps[] | {name: .name, conclusion: .conclusion, number: .number}]}'
gh run view <run-id> --log --job <job-id> | grep -E 'CreateArtifact|UploadArtifact|DownloadArtifact|no artifacts were found|Artifact download failed'
gh api repos/<owner>/<repo>/actions/runs/<run-id>/artifacts --jq '.artifacts[] | {name: .name, size_in_bytes: .size_in_bytes, expired: .expired, created_at: .created_at}'
gh workflow view <workflow-file> --yaml | grep -nE 'needs:|actions/upload-artifact|actions/download-artifact|name:|path:'
gh api repos/<owner>/<repo>/actions/permissions/workflow --jq '{default_workflow_permissions: .default_workflow_permissions, can_approve_pull_request_reviews: .can_approve_pull_request_reviews}'
grep -nE 'actions/upload-artifact|actions/download-artifact' <workflow-file> | awk -F: '{print $1": "$2}' | sort