hashicorp/packer · error

Post-processor failed: %s

Error message

Post-processor failed: %s

What it means

During CoreBuild.Run, each post-processor in the chain is executed via corePP.PostProcessor.PostProcess. If PostProcess returns an error, Run appends "Post-processor failed: %s" to the collected errors and continues with the next post-processor sequence (it does not abort the whole run immediately). The wrapped error names the underlying post-processor failure.

Source

Thrown at packer/build.go:400

				Target: fmt.Sprintf("%s (%s)", b.Name(), corePP.PType),
				Ui:     originalUi,
			}

			if corePP.PName == corePP.PType {
				builderUi.Say(fmt.Sprintf("Running post-processor: %s", corePP.PType))
			} else {
				builderUi.Say(fmt.Sprintf("Running post-processor: %s (type %s)", corePP.PName, corePP.PType))
			}
			var ts *TelemetrySpan
			if corePP.config != nil {
				ts = CheckpointReporter.AddSpan(corePP.PType, "post-processor", corePP.config)
			} else {
				ts = CheckpointReporter.AddSpan(corePP.PType, "post-processor", corePP.HCLConfig)
			}
			artifact, defaultKeep, forceOverride, err := corePP.PostProcessor.PostProcess(ctx, ppUi, priorArtifact)
			ts.End(err)
			if err != nil {
				errors = append(errors, fmt.Errorf("Post-processor failed: %s", err))
				continue PostProcessorRunSeqLoop
			}

			if artifact == nil {
				log.Println("Nil artifact, halting post-processor chain.")
				continue PostProcessorRunSeqLoop
			}

			keep := defaultKeep
			// When user has not set keep_input_artifact
			// corePP.keepInputArtifact is nil.
			// In this case, use the keepDefault provided by the postprocessor.
			// When user _has_ set keep_input_artifact, go with that instead.
			// Exception: for postprocessors that will fail/become
			// useless if keep isn't true, heed forceOverride and keep the
			// input artifact regardless of user preference.
			if corePP.KeepInputArtifact != nil {
				if defaultKeep && *corePP.KeepInputArtifact == false && forceOverride {

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Read the text after "Post-processor failed:" — it is the plugin's own error message identifying the root cause
  2. Run with PACKER_LOG=1 to see the post-processor's detailed logs
  3. Fix the underlying post-processor config (credentials, paths, script exit codes)
  4. Re-run the build; the error was recorded but other post-processors in the sequence may still have run

Example fix

// before (HCL2)
post-processor "shell-local" { script = "./upload.sh" }
// after (HCL2) - make the script fail loudly with diagnostics and correct env
post-processor "shell-local" {
  env = { ARTIFACT_TOKEN = var.token }
  script = "./upload.sh"
  inline = ["set -euo pipefail"]
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate post-processor inputs before the build:
// - check script files exist for shell-local
// - verify credentials/variables referenced by the post-processor are set
code := `test -f ./upload.sh && test -n "$ARTIFACT_TOKEN"`

Try / catch

artifacts, err := build.Run(ctx, ui)
if err != nil {
    var multi *packersdk.MultiError
    if errors.As(err, &multi) {
        for _, e := range multi.Errors {
            if strings.HasPrefix(e.Error(), "Post-processor failed:") {
                log.Printf("post-processor issue, continuing with partial artifacts: %v", e)
            }
        }
    }
    return err
}

Prevention

When it happens

Trigger: Any post-processor's PostProcess(ctx, ui, priorArtifact) returning a non-nil error during a build run — e.g. artifact import failures, checksum mismatches, upload errors, or plugin crashes in the post-processor.

Common situations: vagrant-cloud/artifact upload failing on bad credentials; shell-local post-processor script exiting non-zero; compress post-processor failing on disk space; version mismatch between packer core and an installed post-processor plugin.

Related errors


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/f73d1e238d1ebd36. Report an issue: GitHub.