{"record":{"id":"0f52d4af85b90931","repo":"d2lang/d2","slug":"decode-icon-url-for-stable-diagram-hash-missing-v","errorCode":null,"errorMessage":"decode icon URL for stable diagram hash: missing value","messagePattern":"decode icon URL for stable diagram hash: missing value","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2target/d2target.go","lineNumber":344,"sourceCode":"\t\treturn nil, err\n\t}\n\tout.Write(b[lastWrite:])\n\treturn out.Bytes(), nil\n}\n\nfunc hashJSONValueStart(b []byte, keyEnd int) (int, error) {\n\ti := keyEnd\n\tfor i < len(b) && (b[i] == ' ' || b[i] == '\\t' || b[i] == '\\r' || b[i] == '\\n') {\n\t\ti++\n\t}\n\tif i < len(b) && b[i] == ':' {\n\t\ti++\n\t}\n\tfor i < len(b) && (b[i] == ' ' || b[i] == '\\t' || b[i] == '\\r' || b[i] == '\\n') {\n\t\ti++\n\t}\n\tif i >= len(b) {\n\t\treturn 0, fmt.Errorf(\"decode icon URL for stable diagram hash: missing value\")\n\t}\n\treturn i, nil\n}\n\nfunc stableHashURL(raw json.RawMessage) ([]byte, error) {\n\tfields := make(map[string]json.RawMessage, len(legacyURLFieldOrder))\n\tif err := json.Unmarshal(raw, &fields); err != nil {\n\t\treturn nil, fmt.Errorf(\"decode icon URL for stable diagram hash: %w\", err)\n\t}\n\tif len(fields) != len(legacyURLFieldOrder) {\n\t\treturn nil, fmt.Errorf(\"decode icon URL for stable diagram hash: got %d fields, want %d\", len(fields), len(legacyURLFieldOrder))\n\t}\n\n\tvar out bytes.Buffer\n\tout.WriteByte('{')\n\tfor i, name := range legacyURLFieldOrder {\n\t\tvalue, ok := fields[name]\n\t\tif !ok {","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2target/d2target.go#L326-L362","documentation":"This error comes from the internal parser that scans the raw JSON of an icon URL shape while building a stable diagram hash (hash must be identical across serialization variants). It skips whitespace after a key and, if the JSON ends before any value appears, it reports that the value is missing. It guards the hashing pipeline from truncated or hand-mangled raw JSON.","triggerScenarios":"Calling the stable-hash code path with a raw JSON icon URL payload that ends right after a key/colon, i.e. truncated JSON with no value token before EOF.","commonSituations":"Manually constructed or partially written JSON for icon nearShape/shape URLs, external tools truncating output, or version drift where a serializer emits incomplete objects into the hash input.","solutions":["Inspect the raw icon URL JSON passed into hashing and make sure each key is followed by a complete value","Regenerate the diagram JSON from the library instead of editing it by hand","Validate the JSON parses with encoding/json before feeding it to stable hashing","Check for code that trims or truncates serialized payloads before hashing"],"exampleFix":"// before\nraw := []byte(`{\"val\":\"`)\n// after\nraw := []byte(`{\"val\":\"https://example.com/icon.svg\"}`)","handlingStrategy":"validation","validationCode":"raw := iconURLRawJSON\nif !json.Valid(raw) {\n    return fmt.Errorf(\"icon URL raw JSON is not valid JSON: %s\", raw)\n}\nvar probe map[string]json.RawMessage\nif err := json.Unmarshal(raw, &probe); err != nil {\n    return err\n}\nif len(probe) != len(legacyURLFieldOrder) {\n    return fmt.Errorf(\"icon URL JSON has %d fields, want %d\", len(probe), len(legacyURLFieldOrder))\n}","typeGuard":"func isValidIconURLJSON(raw json.RawMessage) bool {\n    if !json.Valid(raw) {\n        return false\n    }\n    var probe map[string]json.RawMessage\n    return json.Unmarshal(raw, &probe) == nil && len(probe) == len(legacyURLFieldOrder)\n}","tryCatchPattern":"hashed, err := stableHashURL(raw)\nif err != nil {\n    log.Printf(\"icon URL hash skipped, malformed JSON %q: %v\", raw, err)\n    return err\n}","preventionTips":["Always produce icon URL JSON via d2's own marshaling, never by hand","Run json.Valid on any raw JSON before hashing","Never truncate serialized payloads before passing them downstream"],"tags":["json","hashing","d2target"],"backgroundTag":"malformed-json-hash-input","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}