d2lang/d2 · error

ruler does not have entire mono font family %s loaded, is a

Error message

ruler does not have entire mono font family %s loaded, is a style missing?

What it means

Same guard as the regular font family check but for the mono font family (used by code/class/sql_table text). The ruler must have the entire mono family (default SourceCodePro, or the family set by the theme's Mono special rule or `mono` style) loaded, otherwise SetDimensions refuses to proceed.

Source

Thrown at d2graph/d2graph.go:1529

	return nil
}

func appendTextDedup(texts []*d2target.MText, t *d2target.MText) []*d2target.MText {
	if GetTextDimensions(texts, nil, t, nil) == nil {
		return append(texts, t)
	}
	return texts
}

func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler, fontFamily *d2fonts.FontFamily, monoFontFamily *d2fonts.FontFamily) error {
	if ruler != nil && fontFamily != nil {
		if ok := ruler.HasFontFamilyLoaded(fontFamily); !ok {
			return fmt.Errorf("ruler does not have entire font family %s loaded, is a style missing?", *fontFamily)
		}
	}
	if ruler != nil && monoFontFamily != nil {
		if ok := ruler.HasFontFamilyLoaded(monoFontFamily); !ok {
			return fmt.Errorf("ruler does not have entire mono font family %s loaded, is a style missing?", *monoFontFamily)
		}
	}

	if g.Theme != nil && g.Theme.SpecialRules.Mono {
		tmp := d2fonts.SourceCodePro
		fontFamily = &tmp
	}

	for _, obj := range g.Objects {
		obj.Box = &geo.Box{}

		// user-specified label/icon positions
		if obj.HasLabel() && obj.Attributes.LabelPosition != nil {
			scalar := *obj.Attributes.LabelPosition
			position := d2ast.LabelPositionsMapping[scalar.Value]
			obj.LabelPosition = go2.Pointer(position.String())
		}
		if obj.Icon != nil && obj.Attributes.IconPosition != nil {

View on GitHub (pinned to 0d69dca6f5)

Solutions

  1. Load the default mono font: after NewRuler(), call InitFonts with d2fonts.D2Fonts so SourceCodePro variants are present
  2. If overriding monoFontFamily, register every style variant of that family in the ruler
  3. Match the family name exactly (check `mono: <name>` in diagram code / theme Mono rules against registered names)
  4. Pre-validate with ruler.HasFontFamilyLoaded(&d2fonts.SourceCodePro) before rendering

Example fix

// before
ruler, _ := textmeasure.NewRuler()
err := graph.SetDimensions(mtexts, ruler, fontFamily, &myMono) // myMono not registered
// after
ruler, _ := textmeasure.NewRuler()
ruler.InitFonts(d2fonts.D2Fonts) // registers SourceCodePro
ruler.SetFontFamily(myMono.Name, myMono.FilePaths) // or use SourceCodePro
err := graph.SetDimensions(mtexts, ruler, fontFamily, &myMono)
Defensive patterns

Strategy: validation

Validate before calling

ruler, _ := textmeasure.NewRuler()
ruler.InitFonts(d2fonts.D2Fonts) // includes SourceCodePro
mono := d2fonts.SourceCodePro
if graph.Theme != nil && graph.Theme.SpecialRules.Mono {
    // theme forces mono; ensure that family is loaded too
}
if !ruler.HasFontFamilyLoaded(&mono) {
    return fmt.Errorf("mono family %s not fully loaded", mono.Name)
}
err := graph.SetDimensions(mtexts, ruler, fontFamily, &mono)

Type guard

func monoFontReady(ruler *textmeasure.Ruler, mono *d2fonts.FontFamily) bool {
    return ruler != nil && mono != nil && ruler.HasFontFamilyLoaded(mono)
}

Try / catch

if err := graph.SetDimensions(mtexts, ruler, fontFamily, monoFontFamily); err != nil {
    if strings.Contains(err.Error(), "mono font family") {
        ruler.InitFonts(d2fonts.D2Fonts)
        monoFontFamily = &d2fonts.SourceCodePro // safe default
        err = graph.SetDimensions(mtexts, ruler, fontFamily, monoFontFamily)
    }
    return err
}

Prevention

When it happens

Trigger: Calling SetDimensions with a non-nil ruler and non-nil monoFontFamily where ruler.HasFontFamilyLoaded(monoFontFamily) is false; or theme.SpecialRules.Mono / a `mono: true` style selects a family the ruler hasn't fully loaded.

Common situations: Custom rulers built without SourceCodePro; self-hosted font setups registering only some weights; using a custom mono font name in diagram code that was never added to the ruler.

Related errors


AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31). Data as JSON: /api/errors/e7dcdcb14c62b187. Report an issue: GitHub.