subframe7536/maple-font · error · ValueError
No hhea table found.
Error message
No hhea table found.
What it means
adjust_line_height rewrites line-height metrics and requires both the hhea and OS/2 tables to be present in the fontTools font object. This ValueError is raised when the 'hhea' table is missing, meaning the loaded font is malformed or of a type that lacks horizontal header metrics. It fails fast instead of silently writing partial metrics.
Source
Thrown at source/py/utils.py:415
axisValRec = ot.AxisValue() # type: ignore
axisValRec.AxisIndex = axis.AxisOrdering
axisValRec.Flags = 0
axisValRec.Format = 1
axisValRec.ValueNameID = id
axisValRec.Value = 1.0
stat_table.AxisValueArray.AxisValue.append(axisValRec)
stat_table.AxisValueCount += 1
def adjust_line_height(
font: TTFont, factor: float, metric: tuple[float, float]
) -> None:
"""
Adjust the line height of the font by modifying the hhea and OS/2 table.
"""
if "hhea" not in font:
raise ValueError("No hhea table found.")
if "OS/2" not in font:
raise ValueError("No OS/2 table found.")
head = font["head"]
hhea = font["hhea"]
os2 = font["OS/2"]
asc, desc = metric
# Maintain original ascender/descender ratio
ascender_ratio = asc / (asc - desc) # type: ignore
# Calculate target total height
target_total_height = int(round(factor * (asc - desc)))
# Calculate new metrics
new_ascender = int(round(target_total_height * ascender_ratio))
new_descender = new_ascender - target_total_height
print(f"Change vertical metric to [{new_ascender}, {new_descender}]")View on GitHub (pinned to c08fda97fe)
Solutions
- Load the font with fontTools TTFont and ensure the hhea table exists: check `"hhea" in font` before calling.
- Re-export or repair the source font so it includes an hhea table (e.g. via fonttools ttLib or a font editor).
- Verify the build input path points at the correct TTF source, not a subsetted/stripped artifact.
- Upgrade fontTools if an old version failed to read the table from a valid font.
Example fix
// before
# adjust_line_height(font, metric) # raises if hhea missing
// after
from fontTools.ttLib import TTFont
# font = TTFont(path) # ensure proper load
# if "hhea" not in font: raise RuntimeError(f"{path} lacks hhea table")
# adjust_line_height(font, metric) Defensive patterns
Strategy: type-guard
Validate before calling
from fontTools.ttLib import TTFont
def require_tables(path, tables=("hhea", "OS/2")):
font = TTFont(path)
missing = [t for t in tables if t not in font]
if missing:
raise ValueError(f"{path} missing tables: {missing}")
return font Type guard
def has_hhea(font) -> bool:
return "hhea" in font # fontTools TTFont supports __contains__ Try / catch
try:
adjust_line_height(font, metric)
except ValueError as e:
if str(e) == "No hhea table found.":
raise RuntimeError("Input font is malformed: rebuild it with fontTools") from e
raise Prevention
- Always load fonts via fontTools.ttLib.TTFont, never hand-built objects.
- Check required tables (hhea, OS/2) right after loading any external font.
- Don't feed subsetted/stripped fonts into line-height adjustment.
- Keep fontTools up to date so valid tables parse correctly.
When it happens
Trigger: Calling adjust_line_height (via build_nf, build_cn, or build_variable_fonts) on a font object where "hhea" not in font — e.g. a CFF/OTF variant stripped of hhea, a corrupted font file, or passing a non-TTF/incorrectly converted font object.
Common situations: Supplying a source font that lost its hhea table during conversion; pointing the build at a non-font or heavily subsetted font; using a font produced by a tool that dropped hhea; passing the wrong object (not a TTFont with tables loaded).
Related errors
- No OS/2 table found.
- No hhea table found.
- No OS/2 table found.
- Glyph '{glyph_name}' not found in font.
- Font does not have an OS/2 table.
AI-assisted analysis of subframe7536/maple-font@c08fda97fe (2026-08-28).
Data as JSON: /api/errors/beb7a0d46f0d4775.
Report an issue: GitHub.