d2lang/d2 · error
invalid font collection offset
Error message
invalid font collection offset
What it means
After reading the ttcf header, the first font's offset (bytes 12–16) is taken as the base; base must be non-negative and leave room for a 12-byte sfnt header within the data. An out-of-range offset means the collection header lies about where its first font begins.
Source
Thrown at lib/textmeasure/fontface.go:201
value: int16(binary.BigEndian.Uint16(table[offset+4 : offset+6])),
}
}
return pairs, nil
}
func sfntTable(src []byte, tag string) ([]byte, error) {
if len(src) < 12 {
return nil, fmt.Errorf("invalid sfnt: too short")
}
base := 0
if string(src[:4]) == "ttcf" {
if len(src) < 16 || binary.BigEndian.Uint32(src[8:12]) == 0 {
return nil, fmt.Errorf("invalid font collection")
}
base = int(binary.BigEndian.Uint32(src[12:16]))
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)
}View on GitHub (pinned to 0d69dca6f5)
Solutions
- Regenerate the .ttc with a reliable tool (fonttools ttCollection) or use the individual .ttf files.
- Verify the font data integrity (size, checksum) before loading.
- Validate offsets yourself with a quick binary check before passing the data to the library.
Defensive patterns
Strategy: validation
Validate before calling
func ttcOffsetInRange(data []byte) bool {
if string(data[:4]) != "ttcf" || len(data) < 16 { return false }
base := int(binary.BigEndian.Uint32(data[12:16]))
return base >= 0 && base+12 <= len(data)
} Try / catch
if err := loadAndParseFont(path); err != nil {
log.Printf("bad font collection offset in %s: %v", path, err)
return loadSingleFont(fallbackPath)
} Prevention
- Never hand-edit font binaries; rebuild collections with proper tooling
- Validate collection offsets before passing font data to the parser
- Keep canonical font sources under version control with checksums
- Test font loading in CI to catch corrupted assets before deployment
When it happens
Trigger: parseFont on a .ttc whose first-font offset points before the start of the file or past the point where a 12-byte sfnt header would fit.
Common situations: Tampered or corrupted .ttc files; endianness/parse mistakes from pre-processing tools; truncated collections whose offset was not adjusted.
Related errors
- invalid font collection
- invalid kern table length
- invalid sfnt table directory
- checksum error in table: %v
- invalid kern table: too short
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/2e32f29adfb7f98e.
Report an issue: GitHub.