{"record":{"id":"d75dafbc92d72e0d","repo":"d2lang/d2","slug":"dimensions-for-object-label-v-not-found","errorCode":null,"errorMessage":"dimensions for object label %#v not found","messagePattern":"dimensions for object label %#v not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2graph/d2graph.go","lineNumber":995,"sourceCode":"\t\t\tdims = GetTextDimensions(mtexts, ruler, obj.Text(), fontFamily)\n\t\t}\n\t}\n\n\tif shapeType == d2target.ShapeSQLTable && obj.Label.Value == \"\" {\n\t\t// measure with placeholder text to determine height\n\t\tplaceholder := *obj.Text()\n\t\tplaceholder.Text = \"Table\"\n\t\tdims = GetTextDimensions(mtexts, ruler, &placeholder, fontFamily)\n\t}\n\n\tif dims == nil {\n\t\tif obj.Text().Text == \"\" {\n\t\t\treturn d2target.NewTextDimensions(0, 0), nil\n\t\t}\n\t\tif shapeType == d2target.ShapeImage {\n\t\t\tdims = d2target.NewTextDimensions(0, 0)\n\t\t} else {\n\t\t\treturn nil, fmt.Errorf(\"dimensions for object label %#v not found\", obj.Text())\n\t\t}\n\t}\n\n\treturn dims, nil\n}\n\nfunc (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.Ruler, fontFamily *d2fonts.FontFamily, monoFontFamily *d2fonts.FontFamily, labelDims d2target.TextDimensions, withLabelPadding bool) (*d2target.TextDimensions, error) {\n\tdims := d2target.TextDimensions{}\n\tdslShape := strings.ToLower(obj.Shape.Value)\n\n\tif dslShape == d2target.ShapeCode {\n\t\tfontSize := obj.Text().FontSize\n\t\t// 0.5em padding on each side\n\t\tlabelDims.Width += fontSize\n\t\tlabelDims.Height += fontSize\n\t} else if withLabelPadding {\n\t\tlabelDims.Width += INNER_LABEL_PADDING\n\t\tlabelDims.Height += INNER_LABEL_PADDING","sourceCodeStart":977,"sourceCodeEnd":1013,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2graph/d2graph.go#L977-L1013","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nerr := graph.SetDimensions(nil, nil, nil, nil)\n// after\nruler, _ := textmeasure.NewRuler()\nerr := graph.SetDimensions(mtexts, ruler, &d2fonts.D2Fonts.FontFamily(...), &d2fonts.SourceCodePro)","handlingStrategy":"validation","validationCode":"ruler, err := textmeasure.NewRuler()\nif err != nil { return err }\nruler.InitFonts(d2fonts.D2Fonts)\n// ensure every object label is pre-measured:\nfor _, obj := range graph.Objects {\n    if obj.Text().Text != \"\" && obj.Shape.Value != d2target.ShapeImage {\n        found := false\n        for _, mt := range mtexts {\n            if mt.Text == obj.Text().Text { found = true; break }\n        }\n        if !found { return fmt.Errorf(\"unmeasured object label: %q\", obj.Text().Text) }\n    }\n}\nerr := graph.SetDimensions(mtexts, ruler, fontFamily, monoFontFamily)","typeGuard":"func hasDimension(mtexts []*d2target.MText, t *d2target.MText) bool {\n    for _, mt := range mtexts {\n        if mt.Text == t.Text && mt.FontSize == t.FontSize && mt.FontFamily == t.FontFamily {\n            return true\n        }\n    }\n    return false\n}","tryCatchPattern":"if err := graph.SetDimensions(mtexts, ruler, fontFamily, monoFontFamily); err != nil {\n    if strings.Contains(err.Error(), \"dimensions for object label\") {\n        // rebuild mtexts with graph.SetText and retry once with a ruler\n    }\n    return err\n}","preventionTips":["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"],"tags":["go","d2","text-measurement","layout"],"backgroundTag":"text-dimensions-not-found","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}