{"record":{"id":"61196bb0cd5f5a00","repo":"d2lang/d2","slug":"ruler-does-not-have-entire-font-family-s-loaded","errorCode":null,"errorMessage":"ruler does not have entire font family %s loaded, is a style missing?","messagePattern":"ruler does not have entire font family (.+?) loaded, is a style missing\\?","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2graph/d2graph.go","lineNumber":1524,"sourceCode":"\t\t\tw, h = ruler.Measure(fontFamily.Font(t.FontSize, style), t.Text)\n\t\t}\n\t\treturn d2target.NewTextDimensions(w, h)\n\t}\n\n\treturn nil\n}\n\nfunc appendTextDedup(texts []*d2target.MText, t *d2target.MText) []*d2target.MText {\n\tif GetTextDimensions(texts, nil, t, nil) == nil {\n\t\treturn append(texts, t)\n\t}\n\treturn texts\n}\n\nfunc (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler, fontFamily *d2fonts.FontFamily, monoFontFamily *d2fonts.FontFamily) error {\n\tif ruler != nil && fontFamily != nil {\n\t\tif ok := ruler.HasFontFamilyLoaded(fontFamily); !ok {\n\t\t\treturn fmt.Errorf(\"ruler does not have entire font family %s loaded, is a style missing?\", *fontFamily)\n\t\t}\n\t}\n\tif ruler != nil && monoFontFamily != nil {\n\t\tif ok := ruler.HasFontFamilyLoaded(monoFontFamily); !ok {\n\t\t\treturn fmt.Errorf(\"ruler does not have entire mono font family %s loaded, is a style missing?\", *monoFontFamily)\n\t\t}\n\t}\n\n\tif g.Theme != nil && g.Theme.SpecialRules.Mono {\n\t\ttmp := d2fonts.SourceCodePro\n\t\tfontFamily = &tmp\n\t}\n\n\tfor _, obj := range g.Objects {\n\t\tobj.Box = &geo.Box{}\n\n\t\t// user-specified label/icon positions\n\t\tif obj.HasLabel() && obj.Attributes.LabelPosition != nil {","sourceCodeStart":1506,"sourceCodeEnd":1542,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2graph/d2graph.go#L1506-L1542","documentation":"SetDimensions guards its measurement work: if a ruler is supplied, it must have every style variant (regular, bold, italic, etc.) of the given font family loaded, checked via ruler.HasFontFamilyLoaded. A partially loaded ruler means some labels would measure incorrectly, so sizing fails fast with this error.","triggerScenarios":"Calling Graph.SetDimensions with a non-nil ruler and non-nil fontFamily where ruler.HasFontFamilyLoaded(fontFamily) returns false — e.g. a custom Ruler that only loaded a subset of the family's font style files.","commonSituations":"Using a custom-compiled textmeasure.Ruler with self-hosted fonts missing bold/italic variants; fonts embedded but family name mismatched (style applied via near/connections makes D2 request variants); upgrading d2 and forgetting to register newly required font files.","solutions":["Initialize the ruler with the full d2fonts default set (ruler.InitFonts(d2fonts.D2Fonts)) so all variants are loaded","If using custom fonts, register every style variant (regular, bold, italic, bold-italic) under the same family name","Pass nil fontFamily only when all texts are guaranteed pre-measured in mtexts","Check ruler.HasFontFamilyLoaded yourself before calling SetDimensions and fail with a clearer message"],"exampleFix":"// before\nruler, _ := textmeasure.NewRuler() // no fonts loaded\nerr := graph.SetDimensions(mtexts, ruler, &fontFamily, nil) // fails\n// after\nruler, _ := textmeasure.NewRuler()\nruler.InitFonts(d2fonts.D2Fonts)\nerr := graph.SetDimensions(mtexts, ruler, &fontFamily, nil)","handlingStrategy":"validation","validationCode":"ruler, _ := textmeasure.NewRuler()\nruler.InitFonts(d2fonts.D2Fonts)\nif !ruler.HasFontFamilyLoaded(&fontFamily) {\n    return fmt.Errorf(\"font family %s incomplete; register all style variants before SetDimensions\", fontFamily.Name)\n}\nerr := graph.SetDimensions(mtexts, ruler, &fontFamily, monoFontFamily)","typeGuard":"func fontFamilyReady(ruler *textmeasure.Ruler, ff *d2fonts.FontFamily) bool {\n    return ruler != nil && ff != nil && ruler.HasFontFamilyLoaded(ff)\n}","tryCatchPattern":"if err := graph.SetDimensions(mtexts, ruler, fontFamily, mono); err != nil {\n    if strings.Contains(err.Error(), \"does not have entire font family\") {\n        ruler.InitFonts(d2fonts.D2Fonts) // or register missing variants, then retry\n        err = graph.SetDimensions(mtexts, ruler, fontFamily, mono)\n    }\n    return err\n}","preventionTips":["Always build rulers via textmeasure.NewRuler() plus InitFonts(d2fonts.D2Fonts)","When registering custom fonts, add all four style variants under one family name","Keep family names consistent between diagram styles and registered fonts","Call ruler.HasFontFamilyLoaded as a cheap pre-flight before rendering"],"tags":["go","d2","fonts","text-measurement"],"backgroundTag":"font-family-not-loaded","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}