d2lang/d2 · error
theme %d not found
Error message
theme %d not found
What it means
ApplyTheme validates that the requested numeric theme ID exists in the d2themes catalog. If d2themescatalog.Find returns the zero-value Theme, the ID is unknown and the graph's Theme is left unchanged, returning this error instead of applying a bogus theme.
Source
Thrown at d2graph/d2graph.go:1869
}
func (obj *Object) IsDescendantOf(ancestor *Object) bool {
if obj == ancestor {
return true
}
if obj.Parent == nil {
return false
}
return obj.Parent.IsDescendantOf(ancestor)
}
// ApplyTheme applies themes on the graph level
// This is different than on the render level, which only changes colors
// A theme applied on the graph level applies special rules that change the graph
func (g *Graph) ApplyTheme(themeID int64) error {
theme := d2themescatalog.Find(themeID)
if theme == (d2themes.Theme{}) {
return fmt.Errorf("theme %d not found", themeID)
}
g.Theme = &theme
return nil
}
func (g *Graph) PrintString() string {
buf := &bytes.Buffer{}
fmt.Fprint(buf, "Objects: [")
for _, obj := range g.Objects {
fmt.Fprintf(buf, "%v, ", obj.AbsID())
}
fmt.Fprint(buf, "]")
return buf.String()
}
func (obj *Object) IterDescendants(apply func(parent, child *Object)) {
for _, c := range obj.ChildrenArray {
apply(obj, c)View on GitHub (pinned to 0d69dca6f5)
Solutions
- Use a named constant from d2themescatalog (e.g. d2themescatalog.NeutralDefault) instead of a raw number
- Validate the ID against the catalog before calling ApplyTheme
- Update the library version if the theme exists in newer D2 releases
- Check user-facing config for typos in theme IDs
Example fix
// before
err := g.ApplyTheme(999)
// after
theme := d2themescatalog.Find(999)
if theme == (d2themes.Theme{}) {
theme = d2themescatalog.NeutralDefault
}
err := g.ApplyTheme(d2themescatalog.NeutralDefault.ID) Defensive patterns
Strategy: validation
Validate before calling
func themeExists(id int64) bool {
return d2themescatalog.Find(id) != (d2themes.Theme{})
}
if !themeExists(themeID) { return fmt.Errorf("unsupported theme %d", themeID) } Type guard
func isKnownTheme(t d2themes.Theme) bool { return t != (d2themes.Theme{}) } Try / catch
if err := g.ApplyTheme(themeID); err != nil {
log.Printf("theme %d unavailable, using default", themeID)
err = g.ApplyTheme(d2themescatalog.NeutralDefault.ID)
} Prevention
- Use d2themescatalog named constants instead of raw IDs
- Validate user-supplied theme IDs against the catalog before applying
- Pin library versions when relying on newly added theme IDs
When it happens
Trigger: Calling (*d2graph.Graph).ApplyTheme with an int64 theme ID that is not one of the catalog's defined theme IDs (0-300+ known constants like d2themescatalog.NeutralDefault).
Common situations: Hardcoding a theme ID read from user config or a CLI flag without validating it; using a theme constant from a newer D2 version in an older vendored copy; off-by-one or typo in the numeric ID.
Related errors
- no available layout
- no layout resolver configured for layout engine %q
- "%s" is invalid
- %v not found
- expected "shadow" to be true or false
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/1b5384f841022865.
Report an issue: GitHub.