d2lang/d2 · error
invalid %s table bounds
Error message
invalid %s table bounds
What it means
sfntTable parses the sfnt table directory of a TrueType/OpenType font to extract a named table (e.g. 'kern'). It validates that the table's offset and length from the directory record fall within the raw font bytes before slicing. If offset/length would go outside src (including overflow making offset negative), it returns this error instead of panicking on a bad slice.
Source
Thrown at lib/textmeasure/fontface.go:218
if base < 0 || base+12 > len(src) {
return nil, fmt.Errorf("invalid font collection offset")
}
}
n := int(binary.BigEndian.Uint16(src[base+4 : base+6]))
records := base + 12
if n > (len(src)-records)/16 {
return nil, fmt.Errorf("invalid sfnt table directory")
}
for i := 0; i < n; i++ {
record := src[records+16*i : records+16*(i+1)]
if string(record[:4]) != tag {
continue
}
offset := int(binary.BigEndian.Uint32(record[8:12]))
length := int(binary.BigEndian.Uint32(record[12:16]))
if offset < 0 || length < 0 || offset > len(src)-length {
return nil, fmt.Errorf("invalid %s table bounds", tag)
}
return src[offset : offset+length], nil
}
return nil, nil
}
View on GitHub (pinned to 0d69dca6f5)
Solutions
- Verify the font file is a complete, valid TTF/OTF (e.g. open with fonttools or check magic bytes 0x00010000/Otto/true/ttcf)
- Re-download or re-copy the font asset; check size against upstream
- If fonts ship via git-lfs, ensure files are actually materialized, not pointer stubs
- If processing untrusted fonts, treat this error as a rejection of the input rather than a bug
Example fix
// before
raw, _ := os.ReadFile("font.ttf") // truncated file
face, err := NewFontFace(raw)
// after
info, _ := os.Stat("font.ttf")
if info.Size() < 12 { return fmt.Errorf("font file truncated") }
face, err := NewFontFace(raw) Defensive patterns
Strategy: validation
Validate before calling
func validateTTF(src []byte) error {
if len(src) < 12 { return fmt.Errorf("font too short") }
return nil // plus check non-truncated file size before use
} Type guard
func looksLikeSFNT(src []byte) bool {
if len(src) < 12 { return false }
switch string(src[:4]) {
case "\x00\x01\x00\x00", "Otto", "true", "ttcf":
return true
}
return false
} Try / catch
table, err := sfntTable(src, "kern")
if err != nil {
log.Printf("rejecting font: %v", err)
return ErrBadFontAsset
} Prevention
- Verify font file sizes/checksums at build or download time
- Avoid git-lfs pointer stubs reaching production embeds
- Never feed untrusted font bytes without expecting rejection errors
- Test font assets load at app startup, not first render
When it happens
Trigger: Calling d2fonts/fontface loading with a corrupt or truncated .ttf/.otf file, a hand-crafted/malicious font whose table directory declares an offset+length beyond the file, or a font whose Uint32 offset overflows int on 32-bit platforms. Reached via parseLegacyKern while initializing a FontFace for text measurement.
Common situations: Embedding a partially-downloaded or git-lfs-pointer font file; bundling a corrupted font asset; fuzzed/hostile font input; wasm builds where int is 32-bit and large offsets overflow negative.
Related errors
- failed to unmarshal Range from %q: missing End field
- failed to unmarshal Range from %q: missing Start field
- failed to unmarshal Position from %q: expected three fields
- invalid gradient syntax
- no parameters in gradient
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/7e2bd9c23925ac99.
Report an issue: GitHub.