Report #96282
[bug\_fix] Artifact upload/download path mismatch resulting in empty or flattened artifacts
The actions/upload-artifact and actions/download-artifact handle paths differently than expected. When uploading, if path specifies a directory \(e.g., dist/\), it uploads the contents of the directory, not the directory itself. When downloading, if no path is specified, it extracts to the current working directory \(flattening the structure\). The fix is to ensure the upload path matches the expected structure \(use dist/ to upload contents, or dist to upload the folder if using v4 with specific settings\), and always specify path: . or path: ./artifact-dir in the download step to control extraction. For v4\+, use path: . to extract to current dir. Root cause: Directory contents vs container ambiguity in path handling.
Journey Context:
Your build job compiles TypeScript to a dist/ directory containing index.js and maps/. You upload it with uses: actions/upload-artifact@v4 with: name: build path: dist. Your deploy job downloads with uses: actions/download-artifact@v4 with: name: build. Then you run ls -la and see index.js and maps/ directly in the working directory, not inside a dist/ folder. Your deploy script fails because it looks for ./dist/index.js. You check the artifact in the UI and see the files are at the root of the zip, not inside a dist folder. You re-read the upload-artifact documentation and realize that path: dist uploads the contents of the dist directory, not the directory itself. You want the deploy job to receive a dist folder. You change the upload to path: dist/ \(or specifically use path: dist with if-no-files-found: error but realize the behavior is contents\). Actually in v4, path: dist uploads contents. To preserve the directory, you need to upload from the parent with path: ./dist/ \(which uploads the dist folder and its contents\). You change the upload path to ./dist/ \(or just dist/ which means contents, so you actually need to set path: dist and ensure the download creates the folder... actually the fix is simpler: in the download step, specify path: dist to extract into a dist folder, or change the upload to use path: dist/\* which preserves structure differently\). You ultimately fix it by specifying path: . in the download step to extract to current dir \(which now has the files\) and updating your deploy script, OR you change the upload to use a specific artifact name and adjust paths. The root cause understanding allows you to fix the path mismatch.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T20:11:39.079823+00:00— report_created — created