d2lang/d2 · error
dimensions for object label %#v not found
Error message
dimensions for object label %#v not found
What it means
D2 computes label sizes during layout. When measuring object label text, GetTextDimensions looked up the text in the pre-measured texts list (mtexts) and, failing that, fell back to the textmeasure ruler; neither had a measurement for this object's label, so the graph cannot be laid out and this error aborts rendering.
Source
Thrown at d2graph/d2graph.go:995
dims = GetTextDimensions(mtexts, ruler, obj.Text(), fontFamily)
}
}
if shapeType == d2target.ShapeSQLTable && obj.Label.Value == "" {
// measure with placeholder text to determine height
placeholder := *obj.Text()
placeholder.Text = "Table"
dims = GetTextDimensions(mtexts, ruler, &placeholder, fontFamily)
}
if dims == nil {
if obj.Text().Text == "" {
return d2target.NewTextDimensions(0, 0), nil
}
if shapeType == d2target.ShapeImage {
dims = d2target.NewTextDimensions(0, 0)
} else {
return nil, fmt.Errorf("dimensions for object label %#v not found", obj.Text())
}
}
return dims, nil
}
func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.Ruler, fontFamily *d2fonts.FontFamily, monoFontFamily *d2fonts.FontFamily, labelDims d2target.TextDimensions, withLabelPadding bool) (*d2target.TextDimensions, error) {
dims := d2target.TextDimensions{}
dslShape := strings.ToLower(obj.Shape.Value)
if dslShape == d2target.ShapeCode {
fontSize := obj.Text().FontSize
// 0.5em padding on each side
labelDims.Width += fontSize
labelDims.Height += fontSize
} else if withLabelPadding {
labelDims.Width += INNER_LABEL_PADDING
labelDims.Height += INNER_LABEL_PADDINGView on GitHub (pinned to 0d69dca6f5)
Solutions
- Pass a non-nil textmeasure.Ruler to SetDimensions (created via textmeasure.NewRuler()) so labels are measured on demand instead of relying only on mtexts
- Ensure every object label's MText is included in the mtexts slice you pass to SetDimensions
- Check that the object's shape is not relying on an empty label path (labels of empty text return 0,0 automatically)
- Regenerate mtexts with graph.SetText or the standard d2 compilation flow instead of hand-building them
Example fix
// before err := graph.SetDimensions(nil, nil, nil, nil) // after ruler, _ := textmeasure.NewRuler() err := graph.SetDimensions(mtexts, ruler, &d2fonts.D2Fonts.FontFamily(...), &d2fonts.SourceCodePro)
Defensive patterns
Strategy: validation
Validate before calling
ruler, err := textmeasure.NewRuler()
if err != nil { return err }
ruler.InitFonts(d2fonts.D2Fonts)
// ensure every object label is pre-measured:
for _, obj := range graph.Objects {
if obj.Text().Text != "" && obj.Shape.Value != d2target.ShapeImage {
found := false
for _, mt := range mtexts {
if mt.Text == obj.Text().Text { found = true; break }
}
if !found { return fmt.Errorf("unmeasured object label: %q", obj.Text().Text) }
}
}
err := graph.SetDimensions(mtexts, ruler, fontFamily, monoFontFamily) Type guard
func hasDimension(mtexts []*d2target.MText, t *d2target.MText) bool {
for _, mt := range mtexts {
if mt.Text == t.Text && mt.FontSize == t.FontSize && mt.FontFamily == t.FontFamily {
return true
}
}
return false
} Try / catch
if err := graph.SetDimensions(mtexts, ruler, fontFamily, monoFontFamily); err != nil {
if strings.Contains(err.Error(), "dimensions for object label") {
// rebuild mtexts with graph.SetText and retry once with a ruler
}
return err
} Prevention
- Always pass a font-initialized textmeasure.Ruler to SetDimensions instead of relying on pre-measured mtexts
- Regenerate mtexts (graph.SetText) after any graph mutation
- Never hand-build the mtexts slice; use the standard d2 compile flow
- For image shapes remember labels are auto-zeroed — only non-image non-empty labels need measurements
When it happens
Trigger: Calling Graph.SetDimensions/ApplyClasses where an object has a non-empty label (and is not a ShapeImage), the label text is absent from the mtexts slice passed in, and either ruler is nil or the ruler has not measured that exact text/font/size combination.
Common situations: Custom render pipelines that build mtexts manually and skip some labels; calling d2lib compile paths with a nil ruler; text changed after measurement (e.g. icon label applied later); using text with unusual fonts/styles that were not registered with the ruler.
Related errors
- dimensions for class field %#v not found
- dimensions for class method %#v not found
- dimensions for sql_table name %#v not found
- dimensions for sql_table type %#v not found
- dimensions for sql_table constraint %#v not found
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/d75dafbc92d72e0d.
Report an issue: GitHub.