d2lang/d2 · error
invalid sfnt table directory
Error message
invalid sfnt table directory
What it means
The sfnt table directory declares a number of table records (bytes 4–6, 16 bytes each); the parser verifies this count fits within the remaining bytes before iterating. A count larger than the available space means the header is corrupt, so parsing is aborted to avoid out-of-bounds reads.
Source
Thrown at lib/textmeasure/fontface.go:208
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)
}
return src[offset : offset+length], nil
}
return nil, nil
}
View on GitHub (pinned to 0d69dca6f5)
Solutions
- Replace the font with an intact copy and verify checksum.
- Rebuild the font with fonttools (open and re-save repairs directory consistency).
- If the file is a subset intentionally trimmed, re-subset properly so the table directory matches the remaining data.
Defensive patterns
Strategy: validation
Validate before calling
func tableDirFits(data []byte) bool {
if len(data) < 12 { return false }
base := 0
if string(data[:4]) == "ttcf" {
if len(data) < 16 { return false }
base = int(binary.BigEndian.Uint32(data[12:16]))
if base < 0 || base+12 > len(data) { return false }
}
n := int(binary.BigEndian.Uint16(data[base+4 : base+6]))
return n <= (len(data)-base-12)/16
} Try / catch
if err := loadAndParseFont(path); err != nil {
log.Printf("font %s has invalid table directory: %v", path, err)
return defaultFace
} Prevention
- Verify font integrity (size + checksum) at download and build time
- Detect truncated downloads before saving font assets
- Rebuild or re-download fonts rather than shipping partially extracted ones
- Parse all bundled fonts in unit tests so corruption fails the build
When it happens
Trigger: parseFont on a font whose numTables field exceeds the number of 16-byte records that actually fit in the data — i.e. the file is truncated relative to its declared table count.
Common situations: Interrupted downloads; fonts partially extracted from installers or documents; fuzzed/malformed font files.
Related errors
- invalid kern table length
- invalid sfnt: too short
- invalid font collection
- invalid font collection offset
- checksum error in table: %v
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/0a660adc24a28dcd.
Report an issue: GitHub.