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

  1. Regenerate the .ttc with a reliable tool (fonttools ttCollection) or use the individual .ttf files.
  2. Verify the font data integrity (size, checksum) before loading.
  3. 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

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


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