{"record":{"id":"99751b6114b8de51","repo":"d2lang/d2","slug":"empty-map-key-q","errorCode":null,"errorMessage":"empty map key: %q","messagePattern":"empty map key: %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2parser/parse.go","lineNumber":113,"sourceCode":"\t}\n\tif k == nil {\n\t\treturn nil, fmt.Errorf(\"empty key: %q\", key)\n\t}\n\treturn k, nil\n}\n\nfunc ParseMapKey(mapKey string) (*d2ast.Key, error) {\n\tp := &parser{\n\t\treader: strings.NewReader(mapKey),\n\t\terr:    &ParseError{},\n\t}\n\n\tmk := p.parseMapKey()\n\tif !p.err.Empty() {\n\t\treturn nil, fmt.Errorf(\"failed to parse map key %q: %w\", mapKey, p.err)\n\t}\n\tif mk == nil {\n\t\treturn nil, fmt.Errorf(\"empty map key: %q\", mapKey)\n\t}\n\treturn mk, nil\n}\n\nfunc ParseValue(value string) (d2ast.Value, error) {\n\tp := &parser{\n\t\treader: strings.NewReader(value),\n\t\terr:    &ParseError{},\n\t}\n\n\tv := p.parseValue()\n\tif !p.err.Empty() {\n\t\treturn nil, fmt.Errorf(\"failed to parse value %q: %w\", value, p.err)\n\t}\n\tif v.Unbox() == nil {\n\t\treturn nil, fmt.Errorf(\"empty value: %q\", value)\n\t}\n\treturn v.Unbox(), nil","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2parser/parse.go#L95-L131","documentation":"ParseMapKey returns this when the input produced no parse errors but yielded a nil map key — the string was empty or contained nothing usable as a key, so there is no AST node to return.","triggerScenarios":"Calling d2parser.ParseMapKey(\"\") or with a string of only whitespace/newlines such that parseMapKey returns nil.","commonSituations":"Empty section of a generated board file being fed back for editing; string slicing producing blank lines; a template variable that didn't interpolate.","solutions":["Guard the input: trim whitespace and reject empty strings before parsing","Check upstream generation logic for why a blank map key was produced","Skip empty fragments when iterating over lines/blocks of a .d2 file"],"exampleFix":"// before\nmk, _ := d2parser.ParseMapKey(block) // block may be \"\\n\"\n// after\nblock = strings.TrimSpace(block)\nif block == \"\" {\n    return nil, nil // nothing to parse\n}\nmk, err := d2parser.ParseMapKey(block)","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(snippet) == \"\" {\n    return nil, nil // or a explicit error, don't call ParseMapKey\n}\nmk, err := d2parser.ParseMapKey(snippet)","typeGuard":null,"tryCatchPattern":"mk, err := d2parser.ParseMapKey(snippet)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"empty map key\") {\n        return nil, nil // skip empty fragment\n    }\n    return err\n}","preventionTips":["Trim whitespace/newlines before parsing map-key fragments","Filter out blank lines/blocks when processing .d2 content","Verify template variables interpolate before parsing output","Return early on empty sections instead of deferring to the parser"],"tags":["d2","parser","empty-input"],"backgroundTag":"empty-key-input","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}