{"record":{"id":"950279f30eb1a389","repo":"d2lang/d2","slug":"failed-to-parse-key-q-w","errorCode":null,"errorMessage":"failed to parse key %q: %w","messagePattern":"failed to parse key %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2parser/parse.go","lineNumber":94,"sourceCode":"\t\tp.err = &ParseError{}\n\t}\n\n\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 {","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2parser/parse.go#L76-L112","documentation":"d2parser.ParseKey parses a single key string (e.g. 'x.y.z') into a d2ast.Key. The parser accumulates issues in a ParseError; if parsing produced any diagnostics, ParseKey wraps them with this error via %w so callers can inspect the underlying parse error.","triggerScenarios":"Calling ParseKey with a syntactically invalid key: unbalanced quotes/brackets, invalid characters, malformed connection syntax like 'a -> b' passed to ParseKey when arrows need different handling, or a key containing reserved/illegal sequences.","commonSituations":"Building keys dynamically from user input or config that contains spaces or special characters without quoting; using key text extracted from another context (comments, IDs); version changes in d2 grammar making previously valid keys invalid.","solutions":["Inspect the wrapped parse error (errors.Unwrap) for the exact token/position","Quote problematic segments, e.g. 'my key' → '\"my key\"' or use single quotes for IDs with special chars","Sanitize user-supplied key fragments before composing dotted paths","Use d2aster to build keys programmatically instead of string concatenation"],"exampleFix":"// before\nk, err := d2parser.ParseKey(\"my key.sub\") // parse error: space unquoted\n// after\nk, err := d2parser.ParseKey(\"'my key'.sub\")","handlingStrategy":"try-catch","validationCode":"func keyLooksValid(k string) bool {\n    k = strings.TrimSpace(k)\n    if k == \"\" { return false }\n    // disallow obviously unbalanced quotes/brackets\n    return strings.Count(k, \"\\\"\")%2 == 0\n}","typeGuard":null,"tryCatchPattern":"k, err := d2parser.ParseKey(raw)\nif err != nil {\n    if pe := errors.Unwrap(err); pe != nil {\n        // inspect underlying d2parser.ParseError for position\n        return fmt.Errorf(\"invalid key %q: %v\", raw, pe)\n    }\n    return err\n}","preventionTips":["Quote key segments containing spaces or special characters","Build keys programmatically with d2aster instead of string concatenation","Test round-trip: d2fmt.Format the key path before parsing","Keep d2 library versions consistent across generation and parsing code"],"tags":["d2","parser","key-syntax"],"backgroundTag":"key-parse-failed","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}