d2lang/d2 · critical

Failed to decompress FuzzyBubbles-Regular: %v

Error message

Failed to decompress FuzzyBubbles-Regular: %v

What it means

During WASM init, d2fonts decompresses the embedded FuzzyBubbles-Regular brotli blob to register the HandDrawn regular (and italic fallback) font. Failure decompressing that blob panics init with this message. The font is embedded at build time, so failures indicate bad/corrupt embedded data rather than user input.

Source

Thrown at d2renderers/d2fonts/d2fonts_embed_wasm.go:105

	} else {
		FontEncodings.Set(Font{Family: SourceCodePro, Style: FONT_STYLE_BOLD}, str)
	}

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

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

	// Decompress and register FuzzyBubbles fonts
	if str, err := compression.DecompressBrotli(fuzzyBubblesRegularBr); err != nil {
		panic(fmt.Sprintf("Failed to decompress FuzzyBubbles-Regular: %v", err))
	} else {
		FontEncodings.Set(Font{Family: HandDrawn, Style: FONT_STYLE_REGULAR}, str)
		// HandDrawn has no italic, so reuse regular
		FontEncodings.Set(Font{Family: HandDrawn, Style: FONT_STYLE_ITALIC}, str)
	}

	if str, err := compression.DecompressBrotli(fuzzyBubblesBoldBr); err != nil {
		panic(fmt.Sprintf("Failed to decompress FuzzyBubbles-Bold: %v", err))
	} else {
		FontEncodings.Set(Font{Family: HandDrawn, Style: FONT_STYLE_BOLD}, str)
		// HandDrawn has no semibold, so reuse bold
		FontEncodings.Set(Font{Family: HandDrawn, Style: FONT_STYLE_SEMIBOLD}, str)
	}

	// Trim trailing newlines
	trimEncodings()

	// Initialize FontFaces with TTF files

View on GitHub (pinned to 0d69dca6f5)

Solutions

  1. Rebuild from a clean checkout to regenerate/restore the embedded fuzzyBubblesRegular blob
  2. Verify fuzzyBubblesRegularBr decompresses standalone (brotli -d) and replace it if corrupt
  3. Re-encode the FuzzyBubbles-Regular TTF to brotli with the same encoder settings the project uses
  4. Check that the compression package's brotli decoder version is compatible with the asset encoder

Example fix

// before
fuzzyBubbles-regular.ttf.br // empty/invalid
// after
brotli -f fuzzyBubbles-regular.ttf && go build ./...
Defensive patterns

Strategy: validation

Validate before calling

// Validate embedded asset pre-build
import "os/exec"
out, err := exec.Command("brotli", "-d", "-c", "fuzzyBubbles-regular.ttf.br").Output()
if err != nil || len(out) == 0 { panic("fuzzyBubbles-regular.ttf.br is corrupt") }

Prevention

When it happens

Trigger: Process start of a WASM build: init at d2renderers/d2fonts/d2fonts_embed_wasm.go:105 calls compression.DecompressBrotli(fuzzyBubblesRegularBr) and gets a non-nil error — corrupt, truncated, or invalid embedded brotli data.

Common situations: Regenerating embedded font assets with wrong compression settings; corrupted repo files; build pipeline substituting placeholder/empty blobs; incompatibility between brotli encoder and decoder versions.

Related errors


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