hashicorp/packer · error

marshal attestation payload: %w

Error message

marshal attestation payload: %w

What it means

writeAttestation serializes the in-toto statement with json.MarshalIndent when signing mode is `none` (unsigned output). A failure marshaling the statement struct is wrapped as `marshal attestation payload: %w`. This is rare because the statement is a plain Go struct, but non-marshalable fields (channels, funcs, NaN floats) or corrupted internal state trigger it.

Source

Thrown at post-processor/provenance/post-processor.go:285

	predicate, predicateType, err := buildSBOMPredicate(rawSBOM, format)
	if err != nil {
		return err
	}

	statement := internalprovenance.WrapInToto(subjects, predicateType, predicate)
	if err := p.writeAttestation(ctx, ui, statement, paths.SBOMAttestation); err != nil {
		return err
	}

	ui.Say(fmt.Sprintf("Wrote SBOM to %s", paths.SBOMRaw))
	return nil
}

func (p *PostProcessor) writeAttestation(ctx context.Context, ui packersdk.Ui, statement interface{}, outputPath string) error {
	if p.config.SigningMode == internalattestation.SigningModeNone {
		payload, err := json.MarshalIndent(statement, "", "  ")
		if err != nil {
			return fmt.Errorf("marshal attestation payload: %w", err)
		}

		if err := atomicWriteFile(outputPath, payload, 0664); err != nil {
			return fmt.Errorf("write attestation %q: %w", outputPath, err)
		}

		ui.Say(fmt.Sprintf("Wrote attestation to %s", outputPath))
		return nil
	}

	backendConfig, err := p.signingBackendConfig()
	if err != nil {
		return err
	}

	signer, verifier, err := p.signingResources(ctx, backendConfig)
	if err != nil {
		return err

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Inspect the wrapped json error after the colon; it names the offending type/value.
  2. Sanitize numeric fields (replace NaN/Inf) before building the statement.
  3. Check for recent changes to the statement struct that introduced non-serializable fields.
  4. File an issue if the statement comes purely from built-in builder data, as it should always marshal.
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure statement values are JSON-safe before calling PostProcess
if _, err := json.Marshal(statement); err != nil {
    return fmt.Errorf("statement not JSON-serializable: %w", err)
}

Type guard

func isJSONSafe(v interface{}) bool {
    _, err := json.Marshal(v)
    return err == nil
}

Try / catch

if err := pp.PostProcess(ctx, ui, artifact); err != nil {
    if strings.Contains(err.Error(), "marshal attestation payload") {
        // inspect statement fields for NaN/Inf or non-JSON types
    }
}

Prevention

When it happens

Trigger: PostProcess or writeSBOMAttestation hands writeAttestation a statement containing a value json.MarshalIndent cannot encode (e.g. a NaN/Inf number produced by SBOM tooling output, or an unsupported type injected via custom data).

Common situations: Feeding SBOM/provenance data parsed from an external tool where numeric fields contain NaN or the statement carries non-JSON types.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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