{"record":{"id":"f0b677965741f3c7","repo":"hashicorp/packer","slug":"marshal-attestation-payload-w","errorCode":null,"errorMessage":"marshal attestation payload: %w","messagePattern":"marshal attestation payload: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"post-processor/provenance/post-processor.go","lineNumber":285,"sourceCode":"\tpredicate, predicateType, err := buildSBOMPredicate(rawSBOM, format)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tstatement := internalprovenance.WrapInToto(subjects, predicateType, predicate)\n\tif err := p.writeAttestation(ctx, ui, statement, paths.SBOMAttestation); err != nil {\n\t\treturn err\n\t}\n\n\tui.Say(fmt.Sprintf(\"Wrote SBOM to %s\", paths.SBOMRaw))\n\treturn nil\n}\n\nfunc (p *PostProcessor) writeAttestation(ctx context.Context, ui packersdk.Ui, statement interface{}, outputPath string) error {\n\tif p.config.SigningMode == internalattestation.SigningModeNone {\n\t\tpayload, err := json.MarshalIndent(statement, \"\", \"  \")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"marshal attestation payload: %w\", err)\n\t\t}\n\n\t\tif err := atomicWriteFile(outputPath, payload, 0664); err != nil {\n\t\t\treturn fmt.Errorf(\"write attestation %q: %w\", outputPath, err)\n\t\t}\n\n\t\tui.Say(fmt.Sprintf(\"Wrote attestation to %s\", outputPath))\n\t\treturn nil\n\t}\n\n\tbackendConfig, err := p.signingBackendConfig()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tsigner, verifier, err := p.signingResources(ctx, backendConfig)\n\tif err != nil {\n\t\treturn err","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/post-processor/provenance/post-processor.go#L267-L303","documentation":"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.","triggerScenarios":"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).","commonSituations":"Feeding SBOM/provenance data parsed from an external tool where numeric fields contain NaN or the statement carries non-JSON types.","solutions":["Inspect the wrapped json error after the colon; it names the offending type/value.","Sanitize numeric fields (replace NaN/Inf) before building the statement.","Check for recent changes to the statement struct that introduced non-serializable fields.","File an issue if the statement comes purely from built-in builder data, as it should always marshal."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// ensure statement values are JSON-safe before calling PostProcess\nif _, err := json.Marshal(statement); err != nil {\n    return fmt.Errorf(\"statement not JSON-serializable: %w\", err)\n}","typeGuard":"func isJSONSafe(v interface{}) bool {\n    _, err := json.Marshal(v)\n    return err == nil\n}","tryCatchPattern":"if err := pp.PostProcess(ctx, ui, artifact); err != nil {\n    if strings.Contains(err.Error(), \"marshal attestation payload\") {\n        // inspect statement fields for NaN/Inf or non-JSON types\n    }\n}","preventionTips":["Sanitize external SBOM data for NaN/Inf numbers.","Keep statement structs JSON-serializable.","Pin plugin versions so statement schemas stay stable."],"tags":["json","serialization","attestation","provenance"],"backgroundTag":"json-marshal-failed","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}