hashicorp/packer · error

marshal canonical attestation payload: %w

Error message

marshal canonical attestation payload: %w

What it means

For signed attestations, the statement is first serialized into its canonical JSON form via internalattestation.MarshalPayload. A marshal failure is wrapped as `marshal canonical attestation payload: %w`. Canonicalization enforces strict JSON encoding (sorted keys, no extra whitespace), so it fails on values standard MarshalIndent might tolerate.

Source

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

		}

		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
	}

	payload, err := internalattestation.MarshalPayload(statement)
	if err != nil {
		return fmt.Errorf("marshal canonical attestation payload: %w", err)
	}

	bundlePath := sigstoreBundleOutputPath(outputPath)
	bundleJSON := []byte(nil)
	var envelope internalattestation.Envelope
	if backendConfig.Mode == internalattestation.SigningModeKeyless {
		envelope, bundleJSON, err = buildSigstoreBundleForSigner(ctx, signer, backendConfig, internalattestation.InTotoPayloadType, payload)
		if err != nil {
			return fmt.Errorf("sign attestation with Sigstore bundle: %w", err)
		}
	} else {
		signature, signErr := signer.Sign(ctx, internalattestation.InTotoPayloadType, payload)
		if signErr != nil {
			return fmt.Errorf("sign attestation: %w", signErr)
		}
		envelope = internalattestation.NewEnvelope(internalattestation.InTotoPayloadType, payload, signature)
	}

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Read the wrapped error to identify the un-marshalable value.
  2. Sanitize or remove non-finite/non-JSON values from the statement.
  3. Ensure the SBOM source emits valid JSON-compatible data.
  4. Report to the provenance plugin maintainers if it occurs with stock builder data.
Defensive patterns

Strategy: try-catch

Validate before calling

// canonical round-trip check before signing
if b, err := json.Marshal(statement); err != nil {
    return fmt.Errorf("statement not canonicalizable: %w", err)
} else { _ = b }

Type guard

func isCanonicalizable(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 canonical attestation payload") {
        // drop signing_mode or fix non-JSON-safe statement values
    }
}

Prevention

When it happens

Trigger: writeAttestation called with a signing mode other than `none`, where the statement contains values that cannot be canonically encoded (NaN/Inf floats, cycles, unsupported types).

Common situations: SBOM data with non-finite numbers; plugin changes injecting non-JSON-safe fields into the statement before signing.

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/964e8c722e78bc98. Report an issue: GitHub.