{"record":{"id":"125ea5c568f182f1","repo":"OpenNHP/opennhp","slug":"failed-to-unmarshal-evidence-v","errorCode":null,"errorMessage":"failed to unmarshal evidence: %v","messagePattern":"failed to unmarshal evidence: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nhp/core/verifier/verifier.go","lineNumber":76,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode evidence: %v\", err)\n\t}\n\n\tr, err := zlib.NewReader(bytes.NewReader(compressedEvidence))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create zlib reader: %v\", err)\n\t}\n\tdefer r.Close()\n\tevidenceBytes, err := io.ReadAll(r)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read evidence: %v\", err)\n\t}\n\n\tvar evidence map[string]any\n\n\terr = json.Unmarshal(evidenceBytes, &evidence)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to unmarshal evidence: %v\", err)\n\t}\n\n\tvar verifier Verifier\n\n\tif _, ok := evidence[\"test_purpose\"]; ok {\n\t\tverifier, err = NewFallbackVerifier(evidenceBytes)\n\t} else {\n\t\tverifier, err = csv.NewAttestation(string(evidenceBytes))\n\t}\n\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create csv verifier: %v\", err)\n\t} else {\n\t\treturn verifier, nil\n\t}\n}\n","sourceCodeStart":58,"sourceCodeEnd":93,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/nhp/core/verifier/verifier.go#L58-L93","documentation":"Raised in verifier.NewVerifier after successful decompression: json.Unmarshal of the evidence bytes into map[string]any failed. The decompressed payload is not valid JSON, so the dispatcher cannot inspect keys like 'test_purpose' to choose a verifier backend and the evidence is rejected.","triggerScenarios":"NewVerifier's input decompresses to non-JSON content: an HTML error page from the attestation endpoint, a binary blob, or text with encoding issues.","commonSituations":"The confidential-computing evidence URL returned an error page (proxy/interstitial) that was compressed as-is; producer serialized with a non-JSON format; character-encoding corruption in transit.","solutions":["Log the first ~200 bytes of evidenceBytes to see what actually decompressed","Verify the producer (GetEvidenceWithCCUrl) got a 200 with a JSON body — check it isn't compressing an HTML error page","Ensure the attestation service at 127.0.0.1:8006/aa/evidence is running and returning JSON"],"exampleFix":"// before\nreturn nil, fmt.Errorf(\"failed to unmarshal evidence: %v\", err)\n// after\nif json.Valid(evidenceBytes) {\n    err = json.Unmarshal(evidenceBytes, &evidence)\n} else {\n    return nil, fmt.Errorf(\"evidence is not JSON, first bytes: %q\", evidenceBytes[:min(64, len(evidenceBytes))])\n}","handlingStrategy":"validation","validationCode":"if !json.Valid(evidenceBytes) {\n    return errors.New(\"decompressed evidence is not valid JSON\")\n}","typeGuard":null,"tryCatchPattern":"if v, err := verifier.NewVerifier(evidenceB64); err != nil {\n    if strings.Contains(err.Error(), \"failed to unmarshal evidence\") {\n        // dump first bytes of decompressed payload for diagnosis\n    }\n}","preventionTips":["Assert the attestation endpoint returns application/json, not HTML error pages","Log a bounded prefix of decompressed bytes on failure","Test with both CoCo and fallback evidence shapes"],"tags":["json","attestation","parsing","go"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}