hashicorp/packer · error
Can only have 1 input file when not using tar/zip. Found %d
Error message
Can only have 1 input file when not using tar/zip. Found %d files: %v
What it means
Packer's compress post-processor requires tar or zip packaging when the build artifact contains more than one file, because the bare-compression path can only io.Copy a single file into the compressor. The artifact had N != 1 files, so PostProcess aborts with the file count and list.
Source
Thrown at post-processor/compress/post-processor.go:227
// Build an archive, if we're supposed to do that.
switch p.config.Archive {
case "tar":
ui.Say(fmt.Sprintf("Tarring %s with %s", target, compression))
err = createTarArchive(artifact.Files(), output)
if err != nil {
return nil, false, false, fmt.Errorf("Error creating tar: %s", err)
}
case "zip":
ui.Say(fmt.Sprintf("Zipping %s", target))
err = createZipArchive(artifact.Files(), output)
if err != nil {
return nil, false, false, fmt.Errorf("Error creating zip: %s", err)
}
default:
// Filename indicates no tarball (just compress) so we'll do an io.Copy
// into our compressor.
if len(artifact.Files()) != 1 {
return nil, false, false, fmt.Errorf(
"Can only have 1 input file when not using tar/zip. Found %d "+
"files: %v", len(artifact.Files()), artifact.Files())
}
archiveFile := artifact.Files()[0]
ui.Say(fmt.Sprintf("Archiving %s with %s", archiveFile, compression))
source, err := os.Open(archiveFile)
if err != nil {
return nil, false, false, fmt.Errorf(
"Failed to open source file %s for reading: %s",
archiveFile, err)
}
defer source.Close()
if _, err = io.Copy(output, source); err != nil {
return nil, false, false, fmt.Errorf("Failed to compress %s: %s",
archiveFile, err)
}View on GitHub (pinned to eb36e3c3e4)
Solutions
- Add .tar to the output filename (e.g. "output.tar.gz") so multiple files are packaged
- Or set archive to "tar" (or "zip") explicitly in the post-processor config
- Or ensure the builder/artifact produces exactly one file
- Print/inspect artifact files to confirm which files are being compressed
Example fix
// before
output = "out/{{ .BuildName }}.xz"
// after
output = "out/{{ .BuildName }}.tar.xz" Defensive patterns
Strategy: validation
Validate before calling
// enforce single-file compression contract before running the post-processor
if !strings.HasSuffix(cfg.OutputPath, ".tar") && !strings.HasSuffix(cfg.OutputPath, ".zip") {
// bare-compress mode: the artifact must yield exactly one file
// otherwise configure tar packaging
if len(artifact.Files()) != 1 {
return fmt.Errorf("artifact has %d files; use .tar in output_path", len(artifact.Files()))
}
} Try / catch
// Go: detect the config mistake and correct the filename
if err != nil && strings.Contains(err.Error(), "Can only have 1 input file") {
cfg.OutputPath = strings.TrimSuffix(cfg.OutputPath, ".xz") + ".tar.xz"
return pp.PostProcess(ctx, ui, artifact)
} Prevention
- Match the output filename extension to the intended packaging (.tar.gz vs .gz)
- Use packer validate / inspect to confirm the artifact file count
- Explicitly set archive = "tar" when unsure about file count
- Check whether earlier post-processors change artifact composition
When it happens
Trigger: Configured filename/output_path has no .tar/.zip extension (e.g. output "image.gz") while the upstream builder's artifact contains 0 or 2+ files — the default branch of the archive switch is entered with len(artifact.Files()) != 1.
Common situations: Using compression_algorithm like gzip/xz with a bare filename but a builder that emits multiple artifacts (e.g. multiple disks, ISO + checksum); forgetting the .tar in the output filename; post-processors earlier in the chain splitting the artifact.
Related errors
- Error creating tar: %s
- Error creating zip: %s
- Failed to create tar header for %s: %s
- The post-processor %s is unknown by Packer, and is likely pa
- error initializing post-processor '%s': %s
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/f0a5f4dddce3de81.
Report an issue: GitHub.