hashicorp/packer · error
unable to open file %s: %s
Error message
unable to open file %s: %s
What it means
PostProcess-time failure in the checksum post-processor: it opens each artifact file from the input artifact with os.Open to hash it; when the artifact file cannot be opened, the writer is closed and the whole post-process aborts with keep=true. The artifact path and wrapped OS error are reported.
Source
Thrown at post-processor/checksum/post-processor.go:145
checksumFile, err := interpolate.Render(p.config.OutputPath, &p.config.ctx)
if err != nil {
return nil, false, true, err
}
if _, err := os.Stat(checksumFile); err != nil {
newartifact.files = append(newartifact.files, checksumFile)
}
if err := os.MkdirAll(filepath.Dir(checksumFile), os.FileMode(0755)); err != nil {
return nil, false, true, fmt.Errorf("unable to create dir: %s", err.Error())
}
fw, err := os.OpenFile(checksumFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(0644))
if err != nil {
return nil, false, true, fmt.Errorf("unable to create file %s: %s", checksumFile, err.Error())
}
fr, err := os.Open(art)
if err != nil {
fw.Close()
return nil, false, true, fmt.Errorf("unable to open file %s: %s", art, err.Error())
}
if _, err = io.Copy(h, fr); err != nil {
fr.Close()
fw.Close()
return nil, false, true, fmt.Errorf("unable to compute %s hash for %s", ct, art)
}
fr.Close()
_, _ = fw.WriteString(fmt.Sprintf("%x\t%s\n", h.Sum(nil), filepath.Base(art)))
fw.Close()
h.Reset()
}
}
// sets keep and forceOverride to true because we don't want to accidentally
// delete the very artifact we're checksumming.
return newartifact, true, true, nil
}View on GitHub (pinned to eb36e3c3e4)
Solutions
- Verify the artifact files still exist at the reported paths at the time PostProcess runs
- Reorder post-processors so checksum runs directly on the builder output if a prior post-processor moves/deletes files
- Check file permissions on the artifact output directory and files
- Keep output files in the same directory tree Packer wrote them to and avoid external cleanup during the build
Example fix
// before
fr, err := os.Open(art)
if err != nil {
fw.Close()
return nil, false, true, fmt.Errorf("unable to open file %s: %s", art, err.Error())
}
// after
fr, err := os.Open(art)
if err != nil {
fw.Close()
return nil, false, true, fmt.Errorf("unable to open file %s: %w", art, err)
} Defensive patterns
Strategy: validation
Validate before calling
// Go: verify every artifact file exists before post-processing
for _, f := range artifact.Files() {
if _, err := os.Stat(f); err != nil {
log.Fatalf("artifact file missing before checksum: %s: %v", f, err)
}
} Try / catch
artifact, _, _, err := pp.PostProcess(ctx, ui, art)
if err != nil {
if strings.Contains(err.Error(), "unable to open file") {
// artifact files vanished: fix post-processor order / stale paths
}
return err
} Prevention
- Run checksum before post-processors that move/compress/delete artifact files
- Verify artifact.Files() paths exist right before PostProcess in custom tooling
- Don't clean up the build output directory while Packer is running
- Use absolute, stable output locations when chaining post-processors
When it happens
Trigger: os.Open(art) fails for a file listed in the artifact's Files() — the builder's output was deleted/moved between build and post-process, the artifact reports a stale path (common with chained post-processors like compress/artifice changing output locations), or permissions changed.
Common situations: Chaining checksum after another post-processor that consumed/renamed the files; running on shared output where the file was cleaned up; the builder emitting file paths that were relative to a different working directory.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- unable to create dir: %s
- unable to create file %s: %s
- failed to write local binary checksum file: %s
- Unrecognized checksum type: %s
- Error parsing target template: %s
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/d6cdbe08cb811483.
Report an issue: GitHub.