{"record":{"id":"d74238384693c765","repo":"hashicorp/packer","slug":"marshal-artifact-identity-w","errorCode":null,"errorMessage":"marshal artifact identity: %w","messagePattern":"marshal artifact identity: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/provenance/subject.go","lineNumber":66,"sourceCode":"\t\t\tsubjects = append(subjects, Subject{\n\t\t\t\tName: filepath.Base(file),\n\t\t\t\tDigest: DigestSet{\n\t\t\t\t\t\"sha256\": digest,\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\n\t\treturn subjects, nil\n\t}\n\n\tidentity, err := deriveIdentityRecord(artifact)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcanonicalIdentity, err := json.Marshal(identity)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"marshal artifact identity: %w\", err)\n\t}\n\n\tdigest := sha256.Sum256(canonicalIdentity)\n\n\treturn []Subject{{\n\t\tName: fmt.Sprintf(\"%s:%s\", artifact.BuilderId(), artifact.Id()),\n\t\tDigest: DigestSet{\n\t\t\t\"sha256\": hex.EncodeToString(digest[:]),\n\t\t},\n\t}}, nil\n}\n\nfunc deriveIdentityRecord(artifact packersdk.Artifact) (map[string]interface{}, error) {\n\tif artifact == nil {\n\t\treturn nil, fmt.Errorf(\"artifact is nil\")\n\t}\n\n\trecord := map[string]interface{}{","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/internal/provenance/subject.go#L48-L84","documentation":"When the artifact has no files, deriveSubjects falls back to digesting a canonical JSON identity record (builderId, id, optional registry state). If json.Marshal of that identity map fails, the error is wrapped as `marshal artifact identity: %w`. In practice this is rare because map[string]interface{} with JSON-normalized values is almost always marshalable.","triggerScenarios":"The artifact's state at registryimage.ArtifactStateURI contains values json.Marshal cannot encode (e.g. channels, funcs, cyclic structures) that survived normalizeJSONValue, or normalizeJSONValue silently returned the record without normalization on its own error path.","commonSituations":"A custom builder or plugin injects a non-JSON-serializable ArtifactStateURI value; custom Artifact implementations returning exotic State() payloads; unexpected changes in packer-plugin-sdk state types after an SDK upgrade.","solutions":["Inspect the wrapped cause from %w to see which value failed to marshal","Check what the builder stores under registryimage.ArtifactStateURI and make it JSON-serializable","Ensure custom Artifact.State() returns plain JSON-safe types (maps, slices, strings, numbers)","Re-run with a stock builder to confirm the issue is plugin-specific"],"exampleFix":"// before\nrecord[\"state\"] = someRuntimeValue // may be unmarshalable\n// after\nenc, err := json.Marshal(someRuntimeValue)\nif err != nil {\n    return record, nil // omit unusable state instead of failing identity digest\n}\nvar safe interface{}\n_ = json.Unmarshal(enc, &safe)\nrecord[\"state\"] = safe","handlingStrategy":"validation","validationCode":"state := artifact.State(registryimage.ArtifactStateURI)\nif state != nil {\n    if _, err := json.Marshal(state); err != nil {\n        log.Warn(\"artifact state not JSON-serializable; identity digest will use builder info only\")\n    }\n}","typeGuard":"func jsonSafe(v interface{}) bool { _, err := json.Marshal(v); return err == nil }","tryCatchPattern":"subjects, err := provenance.DeriveSubjects(artifact)\nif err != nil {\n    if strings.Contains(err.Error(), \"marshal artifact identity\") { return fmt.Errorf(\"artifact state unusable: %w\", err) }\n    return err\n}","preventionTips":["Store only JSON-safe values under ArtifactStateURI","Round-trip plugin state through json.Marshal/Unmarshal before attaching","Keep packer-plugin-sdk updated together with syft/provenance code"],"tags":["go","json","serialization","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"}