Skip to content
Patens
Back to learn

Reference · 94 codes

Audit codes.

Patens runs a built-in audit module against every project. Each issue it finds is reported with a stable code (e.g. sidebearing-deeply-negative-lsb) so it's referenceable in commits, bug reports, and tutorials. This page is the canonical reference for what every code means.

Codes are grouped by family. Each code in the editor links here, and many issues have a one-click Fix action available inline.

For the marketing-level explanation of why Patens has a teaching audit module — philosophy, comparison vs. other browser-based editors, CLI integration — see /audit.

Contour shape

Issues with the geometry of a glyph's outlines — control points, segments, intersections. These are catchable by the editor without any context about the font as a whole.

empty
Glyph has no outlines yet. Draw at least one contour (or set components) before export.
open-contour
A contour lacks its closing Z command. Open paths still rasterise but break boolean ops and many shaping tools.
duplicate-points
Two consecutive on-curve points sit within 0.5fu of each other — the second adds no information and may cause hinting noise.
off-grid-points
Point coordinates are fractional. Most renderers round to integer font units anyway — snapping explicitly avoids subpixel surprises.
near-collinear-points
A point sits within 1fu of the line between its neighbours — a vestigial node, safe to remove.
sharp-kink
A 5–25° turn between line segments. Probably meant to be a smooth curve or a clean corner.
self-intersecting
A contour crosses itself. Rasterisers fill the overlap unpredictably depending on fill-rule (even-odd vs non-zero).
contour-winding-collision
A nested counter shares its outer contour's direction. Inner contours must run opposite for the counter to render as a hole.
tiny-contour
A contour smaller than 8fu in both dimensions — usually a stray artefact from a boolean op or imported SVG.

Metric alignment

Whether letters that should reach the x-height, cap-height, ascender, or descender actually do. Inconsistent metric alignment is the most common reason a typeface reads as "wobbly" at body size.

xheight-misaligned
A lowercase letter that should reach x-height is sitting noticeably below it. Uneven tops across letters give text a wobbly rhythm; consistent x-height alignment is what makes type read smoothly.
capheight-misaligned
An uppercase letter that should reach cap-height is sitting noticeably below it. Caps lines lose their crisp baseline-and-cap rhythm when individual letters fall short.
extends-above-ascender
The glyph's bbox extends above the OS/2 ascender. Some renderers will clip the top stroke.
extends-below-descender
The glyph's bbox extends below the OS/2 descender. Some renderers will clip the bottom stroke.

Spacing & sidebearings

The horizontal layout of glyphs — advance widths, left and right sidebearings. These checks catch accidental overlaps, zero-width glyphs, and the negative sidebearings that creep in from mass-spacing passes.

zero-advance
The glyph's advance width is 0. Text containing this glyph will have all following glyphs stacked at the same position.
overflows-advance
The drawn glyph extends past its advance width. Adjacent glyphs will overlap — bump the advance or pull the right edge in.
sidebearing-deeply-negative-lsb
Left sidebearing is more negative than -100fu — usually a bug from a mass-spacing pass. Modest negatives (e.g. -20) are normal for italic letters that lean.
sidebearing-deeply-negative-rsb
Right sidebearing is more negative than -100fu — usually a bug from a mass-spacing pass. Modest negatives (e.g. -20) are normal for italic letters that lean or for tightly-tucked terminal shapes (T, Y, V at the end of a word).
sidebearing-class-drift-lsb
This glyph's left sidebearing has drifted from the median of its sidebearing-class peers. Either re-apply the class or remove this glyph from it.
sidebearing-class-drift-rsb
This glyph's right sidebearing has drifted from the median of its sidebearing-class peers. Either re-apply the class or remove this glyph from it — the drift means one of those two is your intent, and leaving the class in place propagates the staleness on the next class edit.
sidebearings-no-classes
The project has no sidebearing classes — every glyph carries its sidebearings independently. For mid-to-large families this gets unmaintainable; sidebearing classes pin shape-similar glyphs (n / m / h / b / d / p / q) together so a tweak propagates.

Composites & references

Composite glyphs are built from component references — Á is A plus the acute mark. These checks catch broken references and infinite-loop component cycles.

composite-cycle
A composite glyph references itself transitively (A → B → A). Rendering would loop forever — exports break. Remove one link in the chain.
composite-missing-base
A composite reference points at a glyph with no outlines. The reference will render as nothing.

Anchors & mark positioning

GPOS mark positioning relies on named anchors — base glyphs declare anchor names (top, bottom), marks declare matching partner names (_top, _bottom). These checks enforce the naming contract and the partner requirement.

anchors-missing
A meaningful number of Latin base glyphs have no anchors. Composites built from them (Á, È, Ñ, Ç) will use fixed offsets rather than proper GPOS mark positioning — marks will look mechanically placed rather than tuned to each letter's shape.
anchor-without-partner
An anchor has no partner on the other side (no mark with the matching "_name" for a base anchor, or no base with the matching "name" for a mark anchor). Info-level because designers often add anchors ahead of drawing the partner glyph — but if you forget the partner, the anchor sits unused at export.
anchor-naming-base-with-prefix
Base-glyph anchors should not start with "_" — that prefix is reserved for mark glyphs. Rename or the GPOS mark feature will miss this attachment point.
anchor-naming-mark-no-prefix
GPOS mark-positioning convention: marks (combining diacritics) carry anchors prefixed with "_" so they pair up with same-named base anchors. Without the prefix, this anchor never enters the mark feature.

OpenType features

Auto-detected OpenType feature integrity — kerning, classes, pair coverage.

feature-kern-disabled-with-pairs
The kern feature is disabled in project.features.kern but kerning pairs exist in project.kerning. The pairs ship in the OTF dead — they're emitted into the file but the off flag tells renderers to skip them. Either enable kern on the Features tab (the typical case once pairs are set) or delete the pair data.
figures-non-tabular
The 0–9 digits have unequal advance widths — proportional figures. Fine for body text; broken for data tables, prices, and spreadsheets where columns of numbers must align. Run "Tabularise 0–9" on the Spacing tab to give every digit the same advance.
kerning-no-classes
The project has many flat kerning pairs and zero kerning classes. Once you have more than ~30 pairs, classes become much more maintainable than direct pairs — grouping accented variants (e.g. @A_left = [A Á Â Ä À]) consolidates kerning across the family.
kerning-class-singleton
A kerning class has exactly one member. Classes are meant to group glyphs that share kerning behavior — a singleton class is identical to a direct pair and just adds a layer to navigate. Either expand it (e.g. visually-similar glyphs to share the value) or replace it with a direct pair on the spacing tab.
kerning-extreme
A kerning pair exceeds half the smaller glyph's advance — almost certainly a decimal typo (e.g. -500 typed when -50 was meant). Check the value in the spacing pair editor.
kerning-pair-self
A kerning pair sets a value where the left and right glyph are the same — at run time this pulls a letter toward itself, which is rarely intended. Usually a typo in the pair editor (accidentally entering the same glyph in both slots). Delete unless the script genuinely needs self-kerning in a compound context.
pair-missing-glyph
A kerning pair references a glyph that doesn't exist in the project. The pair is dead weight — either draw the missing glyph or remove the pair from the spacing tab.
pair-orphan-class
A kerning pair references an undefined kerning class. The pair silently does nothing at run time. Either define the class or change the pair to reference one that exists.
class-empty
A kerning class has no members. Empty classes pull their weight on the maintenance side but contribute nothing at run time — either fill them with the glyphs they're meant to group, or delete them.
class-missing-member
A kerning class lists a codepoint that has no corresponding glyph in the project. The reference is dead — the class behaves as if that member weren't there. Either draw the glyph or remove the reference from the class.
class-name-format
A kerning class name doesn't start with "@" — the convention shared by Glyphs, FontLab, and FEA syntax for kerning groups. Renaming makes the class read uniformly across tools and any FEA you generate.

Glyph naming

Glyph names follow specific rules (production names per Adobe glyph list, length limits, character restrictions). Renderers and font shells fall back to .notdef when names are malformed.

glyph-name-empty
Glyph name field is empty. PostScript glyph names are required for OpenType feature substitutions.
glyph-name-invalid
Glyph name contains characters outside the allowed set (A-Za-z0-9._-) or starts with a digit. The PostScript spec forbids it.
glyph-name-not-canonical
The glyph name differs from the canonical Adobe Glyph List for New Fonts name for this codepoint. Renaming keeps downstream tooling (feature substitutions, color emoji lookups, PostScript naming) consistent.
glyph-name-too-long
Glyph name exceeds 63 characters. The OpenType post-table v2 spec caps individual names at 63 bytes; longer names get silently truncated on export, which can then collide with whatever existing glyph already shares the prefix. Use the AGLFN suggestion chip in the glyph browser to get a canonical short name.
duplicate-glyph-name
Two or more glyphs share the same PostScript name. The OpenType post table requires unique names — OTF export fails. Rename the conflicting glyphs (the AGLFN suggestion chip + bulk AGLFN rename in the glyph browser are the fastest paths).

Vertical metrics

OS/2 and hhea tables hold the vertical metrics renderers use. These two tables must agree or text reflows inconsistently between OS/browser combinations.

metrics-asc-mismatch
OS/2 typoAscender doesn't match hhea ascender. The two values should be equal — line-height computations on Mac/iOS read OS/2, on Windows browsers read hhea, and a mismatch causes line spacing to differ across platforms.
metrics-desc-mismatch
OS/2 typoDescender doesn't match hhea descender. Same platform-divergence story as the ascender mismatch — line spacing won't match between Mac and Windows.
metrics-gap-mismatch
OS/2 typoLineGap doesn't match hhea lineGap. The extra-line-gap above the ascender is platform-dependent unless both fields agree. Set them equal in the Metrics inspector.
metrics-use-typo-off
The USE_TYPO_METRICS flag (OS/2 fsSelection bit 7) is off. Without it, Windows uses winAscent / winDescent for line spacing while Mac uses typoAscender / typoDescender, producing different line heights across platforms. Almost always should be on.
metrics-cap-above-ascender
Cap-height exceeds the ascender. Capital letters will clip when rendered — ascender is the platform-recognised top of the glyph bounding box, caps must fit inside it.
metrics-x-above-cap
x-height exceeds cap-height — lowercase letters would render taller than uppercase. Almost certainly a typo in the metrics inspector.
metrics-descender-nonnegative
Descender is zero or positive — descending letters (g, j, p, q, y) will sit on the baseline rather than dropping below it. Descender values are conventionally negative (e.g. -200 at 1000 UPM).
metrics-win-clip-top
OS/2 winAscent is below typoAscender — top edges of glyphs may clip on Windows. winAscent is Windows' clipping boundary; if it sits below the typoAscender, ascenders that reach typoAscender will be cropped. Bump winAscent up.
metrics-win-clip-bottom
OS/2 winDescent is below |typoDescender| — descenders may clip on Windows. winDescent is the clipping boundary for descenders; if it's smaller than the typoDescender's magnitude, descenders get cropped. Bump winDescent up.
metrics-zero-height
Cap-height or x-height is zero. Several algorithms (auto-spacing, spacing-by-reference, x-height alignment audit) depend on these to be positive — set them in the metrics inspector.

Font metadata

The OS/2 + name-table fields a real shippable font needs — designer, manufacturer, license, vendor ID, version string, copyright.

meta-no-designer
Designer field is empty. Name table ID 9 ships blank, so Glyphs / Font Book / OS font browsers show "Unknown designer". Set it on the Brief tab.
meta-no-designer-url
Designer URL is empty. A homepage or portfolio link surfaces in some font dialogs and in PDF metadata when the font is embedded. Recommended for any font you want credit on.
meta-no-manufacturer
Manufacturer (foundry) field is empty — the name table falls back to the designer name. If you ship under a foundry brand distinct from the designer, set it explicitly so attribution is correct.
meta-no-license
License field is empty. Pick a preset on the Export tab (OFL 1.1 for open source, Proprietary for commercial) so downstream users know the terms — fonts without licenses get treated as untrusted by review tools.
meta-no-license-url
License is set but the license URL is empty. URLs let embedded apps link directly to the license text (e.g. https://scripts.sil.org/OFL for OFL). Strongly recommended for OFL fonts.
meta-no-vendor-id
OS/2 vendor ID is empty — defaults to "NONE" in the exported file. Register a 4-letter foundry tag at https://learn.microsoft.com/typography/vendors/ to identify your fonts in font-management tooling and crash diagnostics.
meta-vendor-id-invalid
Vendor ID is more than 4 characters or contains non-ASCII. The OS/2 achVendID field is 4 bytes — Microsoft's registry uses 4-letter all-caps tags. Short tags will be space-padded; over-length tags get truncated.
meta-version-format
Version string doesn't match the OpenType "MAJOR.MINOR" convention (e.g. "1.000", "2.345"). Many tools parse it into head.fontRevision and round non-conforming strings — best to follow the convention for predictable behavior.
naming-family
Family name is empty. The OpenType name table requires a non-empty family name (ID 1) — export will refuse to produce a file without it. Set it on the Brief or Export tab.
naming-family-chars
Family name contains characters outside the safe set (letters / digits / space / hyphen). Some apps reject anything beyond that — limit to A–Z, a–z, 0–9, space, and hyphen unless you've verified your target apps accept more.
naming-family-long
Family name exceeds 31 characters. Some legacy app menus truncate or refuse to list overly long family names — keeping the name compact avoids ugly fallback behavior in Word, Photoshop, and older Office builds.
naming-style
Style name is empty. The name table requires a style name (ID 2 — e.g. "Regular", "Bold", "Italic"). Export refuses to ship without one.
naming-version
Version field is empty. The OpenType head.fontRevision is derived from this — when empty, export defaults to "1.000". Set it explicitly so each release has a recognisable version string in font dialogs.
naming-designer-missing
Designer field is empty. The name appears in OS font browsers and any metadata-aware tool — leaving it blank shows "Unknown".
naming-license-missing
License field is empty. Distributing without a license leaves recipients guessing about terms. Pick an SPDX identifier (e.g. "OFL-1.1") or paste your custom EULA.

Design brief

Brief completeness — design intent, audience, motivation. The brief drives later editorial decisions and is what makes audit results contextual ("this typeface's brief says 'large display', so a too-thin hairline matters here").

brief-no-intent
The brief's "intent" field is empty. Without a stated intent, audit and review tools can't check whether design choices match the goal. Set one sentence on the Brief tab — e.g. "a geometric sans for product UI at 14px+".
brief-no-design-notes
The brief has no design notes. Notes are where you record decisions ("contrast is monoline", "g is single-storey") so future-you doesn't reinvent them. Not required for export — recommended for any project you'll revisit.
notes-todo
The glyph's notes field contains TODO or FIXME — an unresolved work item the designer left for future iteration.
flagged-for-review
A designer hit Shift+F on this glyph to mark it for follow-up review — a designer-set reminder, not a rule violation. The flag clears with another Shift+F. Useful for batch-marking glyphs that need refinement on a second pass without losing track (e.g. the bespoke Cyrillic shapes Я Ж Ф that ship as sketches in the demo project).

Variable fonts & axes

Designspace integrity for variable fonts — axes, masters, instances. These checks fire when an axis is declared but unused, a master is out of range, or an instance points at an axis that no longer exists.

axis-range-invalid
A designspace axis has min/default/max values out of order. The interpolation engine requires min ≤ default ≤ max — fix the axis on the Designspace tab.
master-axis-missing
A master is missing a value for a declared axis. Interpolation is undefined at that axis — the export pipeline will substitute the axis default, which is rarely what the designer intended.
master-axis-unknown
A master's location references an axis tag the project doesn't declare. The unknown axis is ignored at export — fix by adding the axis to project.axes or removing it from the master's location.
master-axis-out-of-range
A master's axis value sits outside the declared range. The interpolation engine will clip to the nearest valid value, producing unexpected geometry.
master-orphan-axis
A master references an axis the project doesn't declare. The unknown axis is ignored at export, which may produce unexpected interpolation results. Either remove the axis reference from the master's location or add the axis to project.axes.
master-out-of-range
A master's axis value sits outside the declared range. Interpolation will clip to the nearest valid value, producing unexpected geometry. Either move the master into range or widen the axis range to include it.
master-empty
A variable-font master has no glyph overrides — every codepoint falls back to the default master's shape. Either add at least one override (the typical case: the difference is what defines the master) or remove the master from the designspace.
master-contour-count
The number of contours differs across masters. VF interpolation requires identical contour count and order in every master.
master-point-count
A specific contour has different point counts across masters. Same constraint as master-contour-count, one level deeper.
instance-orphan-axis
A named instance references an axis the project doesn't declare. The instance will fall back to axis defaults for the unknown axis — usually not what you want. Remove or re-tag the axis reference.
no-instances
The designspace has axes but no named instances. Most apps expect at least the default instance to be defined (e.g. "Regular") so users have something to pick from the font menu. Add one on the Designspace tab.

Multi-script coverage

Whether a project that declares a script has enough glyphs to be useful in that script. Patens has bulk-coverage codes for Latin-1, currency, math, typographic essentials, and control glyphs.

coverage-latin-1-supp
The Latin-1 Supplement subset is incomplete — accented letters used across Western European languages (À É Ñ Ü etc.). Missing glyphs mean Spanish, French, German, Portuguese, etc. won't render in your font.
coverage-currency
The currency-symbol subset is incomplete (¥ £ € ¢ ¤ etc.). Missing currency glyphs fall back to system fonts in price text — a visible inconsistency on storefronts and invoices.
coverage-math
The math-symbol subset is incomplete (± × ÷ ≠ ≤ ≥ etc.). Missing math glyphs are mostly invisible in body text but show up sharply in data tables and technical writing.
coverage-typo-essentials
The typographic essentials subset is incomplete — basic punctuation and spacing characters that every font needs to feel finished (period, comma, hyphen, space, colon, semicolon, quotes). Some text will render with system-font fallbacks for the missing glyphs.
control-glyphs-missing
The 12-glyph control set (the letters foundries draw first to establish proportion + texture: H, O, n, o, +, period, etc.) is incomplete. These should land before mass-drawing the rest because they set the visual rhythm everything else has to match.
glyph-count-low
The project has fewer than ~95 drawn glyphs — the baseline for "usable font" (A–Z + a–z + 0–9 + basic punctuation). Below that, most real-world text will render with fallback fonts mixed in.

Color fonts

COLR / CPAL integrity — palette indices in COLR layers must exist in CPAL.

color-layer-no-palette
A glyph carries color layers but the project has no palettes defined — the layers won't render. Either define a palette on the Features tab so the layers have somewhere to draw their colors from, or remove the colorLayers from the glyph if the color was experimental.
color-layer-out-of-range
A color layer references a palette slot index that's beyond the shortest palette's color count. That layer renders transparent in any palette that doesn't have a color at that index. Either add more colors to the short palette(s) or change the layer to reference a slot within the existing range.
palette-length-mismatch
Color palettes have different lengths. CPAL requires every palette to share the same color count — when a glyph layer references slot 4 and only the default palette has 5 colors, the alternate palette will fail to render that layer. Trim or pad palettes on the features tab so all share one length.

UPM

Units per em — the font's coordinate grid. Unusual values cause rendering edge cases.

upm-unusual
Units-per-em (UPM) sits outside the typical 1000–2048 range. Most foundries pick 1000 (PostScript convention) or 2048 (TrueType convention). Unusual values still work but may cause off-by-one rounding when other tools assume a standard UPM.

If a code is missing or its description doesn't match what you see in the editor, email hi@patens.design. Accuracy here is the difference between the audit module feeling like a teaching tool and feeling like noise.