{"record":{"id":"2272cca2008522d6","repo":"d2lang/d2","slug":"dimensions-for-sql-table-type-v-not-found","errorCode":null,"errorMessage":"dimensions for sql_table type %#v not found","messagePattern":"dimensions for sql_table type %#v not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2graph/d2graph.go","lineNumber":1107,"sourceCode":"\t\t}\n\n\t\tfor i := range obj.SQLTable.Columns {\n\t\t\t// Note: we want to set dimensions of actual column not the for loop copy of the struct\n\t\t\tc := &obj.SQLTable.Columns[i]\n\n\t\t\tctexts := c.Texts(colFontSize)\n\n\t\t\tnameDims := GetTextDimensions(mtexts, ruler, ctexts[0], fontFamily)\n\t\t\tif nameDims == nil {\n\t\t\t\treturn nil, fmt.Errorf(\"dimensions for sql_table name %#v not found\", ctexts[0].Text)\n\t\t\t}\n\t\t\tc.Name.LabelWidth = nameDims.Width\n\t\t\tc.Name.LabelHeight = nameDims.Height\n\t\t\tmaxNameWidth = go2.Max(maxNameWidth, nameDims.Width)\n\n\t\t\ttypeDims := GetTextDimensions(mtexts, ruler, ctexts[1], fontFamily)\n\t\t\tif typeDims == nil {\n\t\t\t\treturn nil, fmt.Errorf(\"dimensions for sql_table type %#v not found\", ctexts[1].Text)\n\t\t\t}\n\t\t\tc.Type.LabelWidth = typeDims.Width\n\t\t\tc.Type.LabelHeight = typeDims.Height\n\t\t\tmaxTypeWidth = go2.Max(maxTypeWidth, typeDims.Width)\n\n\t\t\tif l := len(c.Constraint); l > 0 {\n\t\t\t\tconstraintDims := GetTextDimensions(mtexts, ruler, ctexts[2], fontFamily)\n\t\t\t\tif constraintDims == nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"dimensions for sql_table constraint %#v not found\", ctexts[2].Text)\n\t\t\t\t}\n\t\t\t\tmaxConstraintWidth = go2.Max(maxConstraintWidth, constraintDims.Width)\n\t\t\t}\n\t\t}\n\n\t\t// The rows get padded a little due to header font being larger than row font\n\t\tdims.Height = go2.Max(12, labelDims.Height*(len(obj.SQLTable.Columns)+1))\n\t\theaderWidth := d2target.HeaderPadding + labelDims.Width + d2target.HeaderPadding\n\t\trowsWidth := d2target.NamePadding + maxNameWidth + d2target.TypePadding + maxTypeWidth + d2target.TypePadding + maxConstraintWidth","sourceCodeStart":1089,"sourceCodeEnd":1125,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2graph/d2graph.go#L1089-L1125","documentation":"During sql_table sizing, each column's type text (ctexts[1]) is measured after the name. A nil result means the type label was neither pre-measured in mtexts nor measurable by the ruler, so the table's column widths cannot be computed and rendering aborts.","triggerScenarios":"Rendering a sql_table where a column's type string at colFontSize is missing from mtexts and ruler is nil or has no measurement for that text/font/size combination.","commonSituations":"Column types set programmatically after mtexts generation; embedded usage passing nil ruler; custom fonts not registered; type text mutated between measurement and sizing passes.","solutions":["Provide an initialized textmeasure.Ruler so types are measured on demand","Regenerate mtexts via graph.SetText after changing column types","Confirm the font family used for table text is loaded into the ruler","Treat sql_table columns as immutable between measurement and SetDimensions"],"exampleFix":"// before\ndims := GetTextDimensions(mtexts, nil, ctexts[1], fontFamily) // nil without ruler\n// after\nruler, _ := textmeasure.NewRuler()\ndims := GetTextDimensions(mtexts, ruler, ctexts[1], fontFamily)","handlingStrategy":"validation","validationCode":"ruler, _ := textmeasure.NewRuler()\nruler.InitFonts(d2fonts.D2Fonts)\nfor _, obj := range graph.Objects {\n    if obj.SQLTable != nil {\n        for _, c := range obj.SQLTable.Columns {\n            typeText := c.Texts(d2fonts.DEFAULT_FONT_SIZE)[1].Text\n            found := false\n            for _, mt := range mtexts { if mt.Text == typeText { found = true; break } }\n            if !found { return fmt.Errorf(\"unmeasured sql_table type: %q\", typeText) }\n        }\n    }\n}","typeGuard":"func sqlTableTypesMeasured(obj *d2graph.Object, mtexts []*d2target.MText) bool {\n    if obj.SQLTable == nil { return true }\n    for _, c := range obj.SQLTable.Columns {\n        txt := c.Texts(d2fonts.DEFAULT_FONT_SIZE)[1].Text\n        found := false\n        for _, mt := range mtexts { if mt.Text == txt { found = true; break } }\n        if !found { return false }\n    }\n    return true\n}","tryCatchPattern":"if err := graph.SetDimensions(mtexts, ruler, fontFamily, mono); err != nil {\n    if strings.Contains(err.Error(), \"dimensions for sql_table type\") {\n        mtexts = graph.SetText(ruler, fontFamily)\n        err = graph.SetDimensions(mtexts, ruler, fontFamily, mono)\n    }\n    return err\n}","preventionTips":["Treat column types as immutable between text measurement and SetDimensions","Regenerate mtexts whenever column type strings change","Use a font-loaded ruler so on-demand measurement is always possible","Prefer the standard d2 compile pipeline over programmatic table construction"],"tags":["go","d2","text-measurement","sql-table"],"backgroundTag":"text-dimensions-not-found","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}