anomalyco/sst · error
failed to read file %s: %w
Error message
failed to read file %s: %w
What it means
uploadAssets resolved a manifest entry to an absolute path (directory + fileKey) and os.ReadFile failed, so the file's contents could not be base64-encoded and uploaded. The wrapped OS error in the message says whether the file is missing (no such file or directory), unreadable (permission denied), or is a directory.
Source
Thrown at pkg/server/resource/cloudflare-worker-assets.go:237
// Find the file path for this hash in the manifest
var fileKey string
var contentType string
for path, entry := range manifest {
if entry.Hash == hash {
fileKey = path
contentType = entry.ContentType
break
}
}
if fileKey == "" {
return "", fmt.Errorf("hash %s not found in manifest", hash)
}
// Read file content
absFilePath := filepath.Join(directory, fileKey)
fileContent, err := os.ReadFile(absFilePath)
if err != nil {
return "", fmt.Errorf("failed to read file %s: %w", absFilePath, err)
}
// Base64 encode the file content
encodedContent := base64.StdEncoding.EncodeToString(fileContent)
// Create form field with content type header
part, err := writer.CreatePart(map[string][]string{
"Content-Disposition": []string{fmt.Sprintf(`form-data; name="%s"; filename="%s"`, hash, hash)},
"Content-Type": []string{contentType},
})
if err != nil {
return "", fmt.Errorf("failed to create form part %s: %w", hash, err)
}
_, err = part.Write([]byte(encodedContent))
if err != nil {
return "", fmt.Errorf("failed to write encoded content for %s: %w", hash, err)
}View on GitHub (pinned to a0bd20f762)
Solutions
- Check the wrapped OS error: 'no such file' means fix the directory path or rebuild assets; 'permission denied' means fix file permissions.
- Verify the 'directory' input matches the actual build output folder (absolute path recommended).
- Rebuild assets before deploy and ensure no cleanup step runs between manifest generation and upload.
- Check file name casing matches exactly (Linux CI filesystems are case-sensitive).
- Ensure the deploy runs on the same machine/container where the assets were built.
Example fix
// before: relative directory resolved from wrong cwd Directory: "dist/client" // after: absolute path anchored to the project root Directory: path.resolve(__root, "dist/client")
Defensive patterns
Strategy: validation
Validate before calling
// pre-flight: every manifest entry must exist and be readable at directory/fileKey
import fs from "fs";
import path from "path";
function validateAssetFiles(manifest, dir) {
for (const file of Object.keys(manifest)) {
const p = path.resolve(dir, file);
const st = fs.statSync(p); // throws ENOENT/EACCES early with a clear path
if (!st.isFile()) throw new Error(`not a file: ${p}`);
fs.accessSync(p, fs.constants.R_OK);
}
} Try / catch
try {
await uploadAssets(manifest, dir);
} catch (e) {
if (String(e).startsWith("failed to read file")) {
const p = String(e).match(/failed to read file (.*?):/)?.[1];
throw new Error(`Asset file unreadable at ${p} - check 'directory' path, file casing, and permissions`);
}
throw e;
} Prevention
- Configure 'directory' as an absolute path to the actual build output
- Run the deploy on the same machine/container where assets were built
- Match filename casing exactly (Linux CI is case-sensitive)
- Ensure no cleanup step deletes assets between build and upload
When it happens
Trigger: The asset file at directory/fileKey does not exist at upload time (deleted or renamed after the manifest was built), directory points at the wrong local folder, file permissions block reading, or fileKey contains path separators that don't resolve on the current OS.
Common situations: Deploying from a machine/CI where the build output directory path differs from the configured 'directory' input; assets cleaned by a later build step before upload; case-sensitive vs case-insensitive filesystem mismatches (macOS dev vs Linux CI); permission-restricted files in the output dir.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- failed to open archive: %w
- failed to create output directory: %w
- failed to copy %s to %s: %w
- failed to copy source files: %w
- failed to create destination file: %w
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/22bbd332cf8da6c7.
Report an issue: GitHub.