d2lang/d2 · critical

Failed to decompress SourceSansPro-Regular: %v

Error message

Failed to decompress SourceSansPro-Regular: %v

What it means

In the WASM build, SourceSansPro Regular font data is embedded brotli-compressed and decompressed in a package init(). If compression.DecompressBrotli fails, init panics with this message, so the process/instance fails to start. It means the embedded font blob is corrupt or the brotli decoder failed.

Source

Thrown at d2renderers/d2fonts/d2fonts_embed_wasm.go:55

//go:embed encoded/SourceCodePro-Italic.txt.br
var sourceCodeProItalicBr []byte

//go:embed encoded/FuzzyBubbles-Regular.txt.br
var fuzzyBubblesRegularBr []byte

//go:embed encoded/FuzzyBubbles-Bold.txt.br
var fuzzyBubblesBoldBr []byte

//go:embed ttf/*
var fontFacesFS embed.FS

func init() {
	FontEncodings = syncmap.New[Font, string]()

	// Decompress and register SourceSansPro fonts
	if str, err := compression.DecompressBrotli(sourceSansProRegularBr); err != nil {
		panic(fmt.Sprintf("Failed to decompress SourceSansPro-Regular: %v", err))
	} else {
		FontEncodings.Set(Font{Family: SourceSansPro, Style: FONT_STYLE_REGULAR}, str)
	}

	if str, err := compression.DecompressBrotli(sourceSansProBoldBr); err != nil {
		panic(fmt.Sprintf("Failed to decompress SourceSansPro-Bold: %v", err))
	} else {
		FontEncodings.Set(Font{Family: SourceSansPro, Style: FONT_STYLE_BOLD}, str)
	}

	if str, err := compression.DecompressBrotli(sourceSansProSemiboldBr); err != nil {
		panic(fmt.Sprintf("Failed to decompress SourceSansPro-Semibold: %v", err))
	} else {
		FontEncodings.Set(Font{Family: SourceSansPro, Style: FONT_STYLE_SEMIBOLD}, str)
	}

	if str, err := compression.DecompressBrotli(sourceSansProItalicBr); err != nil {
		panic(fmt.Sprintf("Failed to decompress SourceSansPro-Italic: %v", err))

View on GitHub (pinned to 0d69dca6f5)

Solutions

  1. Rebuild the wasm bundle ensuring d2fonts embedded assets are generated/embedded intact
  2. Verify the .br asset bytes are non-empty and valid brotli (decompress standalone with a brotli CLI)
  3. Regenerate the brotli-compressed font files with the same toolchain the project uses
  4. If the panic persists in a custom build, diff your build against upstream d2's wasm build script

Example fix

// before (custom build)
rm d2renderers/d2fonts/*.br && git checkout -- d2renderers/d2fonts/*.br
make wasm
// after: init() decompresses without panic
Defensive patterns

Strategy: fallback

Validate before calling

if str, err := compression.DecompressBrotli(sourceSansProRegularBr); err != nil {
    log.Printf("font init failed: %v; falling back to defaults", err)
}

Try / catch

defer func() {
    if r := recover(); r != nil {
        log.Printf("d2fonts init panic: %v", r)
        useSystemFonts = true
    }
}() // note: panics in init() are fatal in Go; the real guard is a correct build

Prevention

When it happens

Trigger: Any use of the wasm d2fonts package where the embedded sourceSansProRegularBr bytes fail brotli decompression — typically a broken build/embed step (wrong or empty asset embedded) rather than runtime user input.

Common situations: Custom wasm builds where the fonts_embed assets weren't generated correctly; truncated embedded assets after aggressive bundler minification; mismatched compression tooling versions when regenerating the .br files.

Related errors


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