d2lang/d2 · error
cannot rename to reserved keyword: %#v
Error message
cannot rename to reserved keyword: %#v
What it means
Rename rejects newName values that collide with d2 reserved keywords (like shape, style, label, etc.) because those identifiers cannot be used as regular object keys; the library returns "cannot rename to reserved keyword" instead of producing a broken diagram.
Source
Thrown at d2oracle/edit.go:1731
if boardG == nil {
return nil, "", fmt.Errorf("board %v not found", boardPath)
}
}
if len(mk.Edges) > 0 && mk.EdgeKey == nil {
// TODO: Not a fan of this dual interpretation depending on mk.Edges.
// Maybe we remove Rename and just have Move.
mk2, err := d2parser.ParseMapKey(newName)
if err != nil {
return nil, "", err
}
mk2.Key = mk.Key
mk = mk2
} else {
_, ok := d2ast.ReservedKeywords[newName]
if ok {
return nil, "", fmt.Errorf("cannot rename to reserved keyword: %#v", newName)
}
if mk.Key != nil {
obj, ok := boardG.Root.HasChild(d2graph.Key(mk.Key))
if !ok {
return nil, "", fmt.Errorf("key does not exist")
}
// If attempt to name something "x", but "x" already exists, rename it "x 2" instead
generatedName, _, err := generateUniqueKey(boardG, newName, obj, nil)
if err == nil {
newName = generatedName
}
}
// TODO: Handle mk.EdgeKey
mk.Key.Path[len(mk.Key.Path)-1] = d2ast.MakeValueBox(d2ast.RawString(newName, true)).StringBox()
}
g, err = move(g, boardPath, key, d2format.Format(mk), false)
return g, newName, errView on GitHub (pinned to 0d69dca6f5)
Solutions
- Validate newName against d2ast.ReservedKeywords before calling Rename.
- Sanitize/escape user-supplied names (prefix, quote, or reject reserved words in UI).
- Pick a different name for the object.
- If a reserved name is genuinely needed, wrap it appropriately in the source rather than via Rename.
Example fix
// before
d2oracle.Rename(g, nil, "db", "style") // rejected
// after
if _, reserved := d2ast.ReservedKeywords[newName]; reserved {
newName = newName + "-node"
}
d2oracle.Rename(g, nil, "db", newName) Defensive patterns
Strategy: validation
Validate before calling
import "oss.terrastruct.com/d2/lib/d2ast"
if _, reserved := d2ast.ReservedKeywords[newName]; reserved {
return fmt.Errorf("%q is a reserved d2 keyword; pick another name", newName)
} Type guard
func isAllowedName(name string) bool {
_, reserved := d2ast.ReservedKeywords[name]
return name != "" && !reserved
} Try / catch
ng, _, err := d2oracle.Rename(g, boardPath, key, newName)
if err != nil && strings.Contains(err.Error(), "reserved keyword") {
return suggestAlternativeName(newName)
} Prevention
- Validate user input against d2ast.ReservedKeywords before calling.
- Sanitize names in UI (block reserved words in autocomplete).
- Add a suffix/quote strategy for reserved names in refactors.
- Test rename flows with reserved words in CI.
When it happens
Trigger: Calling Rename with newName equal to any key in d2ast.ReservedKeywords, e.g. renaming an object to "shape" or "style" when it has no edge interpretation.
Common situations: Renaming based on raw user input in editors; scripted refactors that don't sanitize names; autocompletion suggesting reserved words.
Related errors
- expected "double-border" to be true or false
- cannot connect to reserved keyword
- edge key must be reserved
- cannot rename edge to node
- cannot rename edge to edge chain
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/a12131cf66ee41d4.
Report an issue: GitHub.