{"record":{"id":"47740fb73df5b25c","repo":"d2lang/d2","slug":"empty-key-q","errorCode":null,"errorMessage":"empty key: %q","messagePattern":"empty key: %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2parser/parse.go","lineNumber":97,"sourceCode":"\tm := p.parseMap(true)\n\tif !p.err.Empty() {\n\t\treturn m, p.err\n\t}\n\treturn m, nil\n}\n\nfunc ParseKey(key string) (*d2ast.KeyPath, error) {\n\tp := &parser{\n\t\treader: strings.NewReader(key),\n\t\terr:    &ParseError{},\n\t}\n\n\tk := p.parseKey()\n\tif !p.err.Empty() {\n\t\treturn nil, fmt.Errorf(\"failed to parse key %q: %w\", key, p.err)\n\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","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2parser/parse.go#L79-L115","documentation":"ParseKey returns this when parsing succeeded without diagnostics but produced a nil key — meaning the input string was empty or contained nothing that constitutes a key. It signals the caller passed an empty string rather than malformed syntax.","triggerScenarios":"Calling d2parser.ParseKey(\"\") or ParseKey with a string containing only whitespace/comments so parseKey returns nil.","commonSituations":"Config value or loop variable that is empty due to an earlier failed lookup; splitting a path that produced an empty segment; template rendering left the key blank.","solutions":["Check that the key string is non-empty (after trimming whitespace) before calling ParseKey","Trace where the empty string originates (empty config field, failed split, unset variable)","Skip or default empty keys instead of passing them to the parser"],"exampleFix":"// before\nk, _ := d2parser.ParseKey(strings.TrimSpace(name)) // name may be \"\"\n// after\nname = strings.TrimSpace(name)\nif name == \"\" {\n    return fmt.Errorf(\"cannot resolve empty key\")\n}\nk, err := d2parser.ParseKey(name)","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(raw) == \"\" {\n    return nil, fmt.Errorf(\"refusing to parse empty key\")\n}\nk, err := d2parser.ParseKey(raw)","typeGuard":null,"tryCatchPattern":"k, err := d2parser.ParseKey(raw)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"empty key\") {\n        // treat as missing input; skip or default\n        return nil, nil\n    }\n    return err\n}","preventionTips":["Trim and check inputs before every ParseKey call","Guard loop variables that come from splitting strings","Fail fast when config fields feeding keys are empty","Skip blank lines when iterating .d2 file content"],"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"}