d2lang/d2 · error

decode diagram hash JSON: got closing token %v, want ]

Error message

decode diagram hash JSON: got closing token %v, want ]

What it means

Symmetric to the object-close check: while walking nested JSON, every array must be closed with ']'. A different closing token triggers this error, indicating malformed structure in the diagram JSON being stable-hashed.

Source

Thrown at d2target/d2target.go:317

			closeToken, err := dec.Token()
			if err != nil {
				return err
			}
			if closeToken != json.Delim('}') {
				return fmt.Errorf("decode diagram hash JSON: got closing token %v, want }", closeToken)
			}
		case '[':
			for dec.More() {
				if err := walkValue(); err != nil {
					return err
				}
			}
			closeToken, err := dec.Token()
			if err != nil {
				return err
			}
			if closeToken != json.Delim(']') {
				return fmt.Errorf("decode diagram hash JSON: got closing token %v, want ]", closeToken)
			}
		default:
			return fmt.Errorf("decode diagram hash JSON: unexpected delimiter %q", delim)
		}
		return nil
	}

	if err := walkValue(); err != nil {
		return nil, err
	}
	out.Write(b[lastWrite:])
	return out.Bytes(), nil
}

func hashJSONValueStart(b []byte, keyEnd int) (int, error) {
	i := keyEnd
	for i < len(b) && (b[i] == ' ' || b[i] == '\t' || b[i] == '\r' || b[i] == '\n') {
		i++

View on GitHub (pinned to 0d69dca6f5)

Solutions

  1. Validate the JSON with json.Valid before hashing
  2. Re-serialize from the compiled diagram instead of editing serialized output
  3. Fix the upstream producer emitting mismatched array closers

Example fix

// before
b = []byte(`{"icon": ["url"}`) // missing ]
// after
b = []byte(`{"icon": ["url"]}`)
Defensive patterns

Strategy: validation

Validate before calling

if !json.Valid(b) {
	return errors.New("diagram JSON is malformed")
}

Prevention

When it happens

Trigger: Stable-hashing JSON where an array is closed with '}' or another token instead of ']' — corrupt or hand-edited diagram JSON.

Common situations: Regex/text-based edits to diagram JSON; truncated cached JSON; generated JSON from a buggy custom serializer.

Related errors


AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31). Data as JSON: /api/errors/e446f28bde74463b. Report an issue: GitHub.