This page covers common issues encountered when patching fonts with font-patcher, installing patched fonts, and running the batch patching scripts. For general usage instructions and options, see the Font Patching System and Using the Font Patcher pages. For installation methods, see Installation.
The patcher uses two independent checks to determine whether a source font is monospaced.
Diagram: Monospace Detection Flow
Sources: font-patcher215-241 font-patcher189-205
The function is_monospaced() spot-checks specific glyphs (I, M, W, a, i, m, .) against each other. If any glyph is missing, the function falls back to reading font.os2_panose. There is a deliberate exception for glyphs 0x69 (i) and 0x2E (.): if these glyphs are narrower than the common width but their bounding box also fits within it, the font is still considered monospaced (this accommodates fonts like Code New Roman and Hermit Light/Bold).
Some Windows applications rely on the OS/2 Panose table rather than actual glyph widths. The patcher's force_panose_monospaced() function addresses this by checking font.os2_panose[0] (Family Kind) and font.os2_panose[3] (Proportion):
| Panose Field | Index | Required Value for Monospaced |
|---|---|---|
| Family Kind | [0] | 2 (Latin Text) or 3 (Latin Hand Written) |
| Proportion | [3] | 9 (Monospaced) |
If panose[0] is 0 (Any/default), the patcher sets it to 2. If panose[0] is 2 and panose[3] is not 9, it forces panose[3] to 9.
Fix: Use the --mono flag (or -s) when patching, which calls set_sourcefont_glyph_widths() to force equal advance widths across all glyphs and triggers force_panose_monospaced().
Sources: font-patcher243-255 font-patcher189-213
The patcher logs Panose-related changes at INFO level. To see these messages, pass --debug 2 (output to terminal) or --debug 3 (output to both terminal and file).
fontforge -script font-patcher --debug 2 MyFont.ttf --complete
The helper panose_check_to_text() converts the integer returned by check_panose_monospaced() to a human-readable string:
| Return Value | Meaning |
|---|---|
0 | Panose says "not monospaced" |
1 | Panose says "monospaced" |
-1 | Panose data is invalid (family kind out of range 2–5) |
This indicates the source font has inconsistent glyph widths (the font "lies" about being monospaced). The patcher will log a warning. Use --mono to force uniform widths on the output.
Sources: font-patcher189-213 font-patcher243-255
After FontForge generates the output font, the patcher's TableHEADWriter class reopens the raw font file as binary and adjusts fields that FontForge does not preserve correctly from the source font. These include lowestRecPPEM, ppem_to_int flag bits, xAvgCharWidth, and the HEAD table's checksumAdjustment.
Diagram: TableHEADWriter Checksum Correction Pipeline
Sources: font-patcher477-519
These messages are emitted by calc_full_checksum() and calc_table_checksum() respectively when their check=True parameter is used. They indicate a corrupt or structurally invalid input font file.
calc_full_checksum() uses the constant 0xB1B0AFBA as defined by the OpenType spec.calc_table_checksum() verifies the HEAD table's stored checksum against the calculated value.Fix: Validate the source font using a tool like fonttools (ttx) or FontForge's built-in validation before patching. The patcher exits with sys.exit("Checksum of whole font is bad") when this is detected.
This error is logged at ERROR level (not fatal) from the except Exception as error block in generate(). It occurs when TableHEADWriter cannot parse the binary font structure — most commonly when the output file was not written or is less than 1 byte in size.
The patcher checks for this first:
if not os.path.isfile(outfile) or os.path.getsize(outfile) < 1:
logger.critical("Something went wrong and Fontforge did not generate the new font")
sys.exit(1)
This critical error usually means FontForge itself encountered an internal error. Check the terminal output above this message for FontForge's own error messages.
Sources: font-patcher478-519
When --removeligs / --removeligatures is passed, remove_ligatures() reads the [Subtables] section of a config file and calls sourceFont.removeLookupSubtable(subtable) for each entry.
Diagram: Ligature Removal Code Path
Sources: font-patcher802-817
| Symptom | Likely Cause | Fix |
|---|---|---|
| "No ligature data (config file missing?)" | --removeligs used without --configfile | Pass --configfile path/to/config.cfg |
| "Failed to remove subtable: X" | Subtable name does not exist in source font | Verify subtable names with FontForge's GUI or fonttools |
| Ligatures still present after patching | Config's ligatures JSON list is empty or wrong | Check [Subtables] section in config.cfg; confirm JSON is valid |
The config file's [Subtables] section must contain a ligatures key whose value is a JSON array of subtable name strings. For an example, see the SpaceMono config.cfg entry described in Source Font Examples.
Sources: font-patcher802-817
The patcher scales each symbol glyph set relative to the source font's cell dimensions, stored in self.font_dim. A key check occurs before any glyph copying:
When self.font_extrawide is True, double-width Powerline glyphs are suppressed for that run.
Sources: font-patcher374-376
The ScaleRules key in each patch_set entry controls per-glyph-set scaling. Each rule can specify a scale factor or a measurement method. These are applied by copy_glyphs() within the patching loop.
Fixes to try:
--adjust-line-height (-l) to let the patcher attempt to center Powerline separator glyphs.--cell CELLOPT to manually specify the source cell dimensions, e.g., --cell "0:1000:-200:800". Pass --cell "?" to query detected values without patching.--variable-width-glyphs to avoid forcing glyph advance widths.Sources: font-patcher374-376 font-patcher391-428
This warning appears when the font's height-to-width ratio is too close to square for double-width Powerline glyphs to make sense. It is not an error; the patcher continues but skips double-width Powerline glyphs. If this behavior is undesirable, check whether the source font's vertical metrics (hhea_ascent, hhea_descent) are set correctly.
CRITICAL: Can not find symbol glyph directory ./src/glyphs
(probably you need to download the src/glyphs/ directory?)
This is emitted when self.args.glyphdir does not exist as a directory on disk.
Cause: The src/glyphs/ directory is not included in releases of individual font files. It is only present in:
FontPatcher.zip archive from releasesFix: Download FontPatcher.zip from the latest release and extract it fully. Do not use only the font-patcher script file alone.
Sources: font-patcher383-386
CRITICAL: Can not find symbol source for 'Font Awesome' (i.e. ./src/glyphs/FontAwesome.otf)
Cause: A specific glyph source file is missing from glyphdir. Either the archive was partially extracted or the --glyphdir path points to the wrong location.
Sources: font-patcher405-411
Nerd Fonts: FontForge module could not be loaded. Try installing fontforge python bindings
[e.g. on Linux Debian or Ubuntu: `sudo apt install fontforge python3-fontforge`]
This is the ImportError handler at the top of font-patcher.
| Platform | Resolution |
|---|---|
| Debian/Ubuntu | sudo apt install fontforge python3-fontforge |
| macOS (Homebrew) | brew install fontforge |
| AppImage | Download FontForge AppImage from fontforge/fontforge releases; invoke as ./FontForge.AppImage -script font-patcher ... |
| Docker | Use nerdfonts/patcher image — FontForge is pre-installed |
Sources: font-patcher31-39
Nerd Fonts: configparser module is probably not installed. Try `pip install configparser`
On Python 3, configparser is part of the standard library. If this error appears, your Python environment may be unusually stripped. Verify with python3 -c "import configparser".
Sources: font-patcher26-29
The patcher logs reduced naming functionality if FontnameParser cannot be imported:
Fix: Ensure the directory bin/scripts/name_parser/ is present alongside font-patcher. This directory is included in FontPatcher.zip.
Sources: font-patcher41-47 font-patcher625-626
install.sh's collect_files() function found no font files matching the selected variant and extension in patched-fonts/. This typically occurs because:
--mono when only non-mono files are present).The script searches for files matching patterns:
*NerdFont* (excluding *NerdFontMono* and *NerdFontPropo*)--mono / -s: *NerdFontMono*--use-proportional-glyphs / -p: *NerdFontPropo*Sources: install.sh151-168 install.sh195-198
The install script writes to these directories depending on OS and --install-to-system-path vs. --install-to-user-path (default):
| OS | User Path | System Path |
|---|---|---|
| Linux | ~/.local/share/fonts/NerdFonts | /usr/local/share/fonts/NerdFonts |
| macOS | ~/Library/Fonts/NerdFonts | /Library/Fonts/NerdFonts |
If $XDG_DATA_HOME is set, that overrides the Linux user path.
Sources: install.sh172-187
After installation, install.sh automatically runs fc-cache if it is found on the system PATH.
Diagram: Post-install fc-cache Invocation
Sources: install.sh247-265
Note: The script explicitly catches exit code 1 from fc-cache as success because some versions of fc-cache return 1 even on a successful cache refresh.
Manual fix if automatic refresh did not run:
fc-list | grep Nerd.fc-cache -v will list all scanned directories.CRITICAL: Source font is a variable open type font (VF) and the patch results will most likely not be what you want
This is logged after generate() completes when self.args.is_variable is True. The output font is still written, but variable font axes and instances are not properly handled by FontForge's patching pipeline. The warning is at CRITICAL level but does not call sys.exit().
Workaround: Extract a static instance from the variable font using fonttools before patching:
Sources: font-patcher520-521
| Problem | Key Code Location | Log Level | Resolution |
|---|---|---|---|
| Font not monospaced | is_monospaced(), assert_monospace() | WARNING | Use --mono |
| Bad Panose values | force_panose_monospaced() | INFO | Use --mono |
| HEAD checksum bad | TableHEADWriter.calc_full_checksum() | — (sys.exit) | Validate source font |
| Font not generated | generate() size check | CRITICAL | Check FontForge stderr |
| Font flags error | generate() except block | ERROR | Usually non-fatal |
| Ligature removal fail | remove_ligatures() | ERROR | Check subtable names in config |
| Missing glyphs dir | patch() isdir check | CRITICAL | Extract full FontPatcher.zip |
| Missing symbol file | patch() isfile check | CRITICAL | Verify --glyphdir contents |
| Variable font warning | generate() is_variable check | CRITICAL | Extract static instance first |
| fc-cache not refreshed | install.sh end | — | Run fc-cache -vf manually |
| Font not found post-install | — | — | Check fc-list, verify font dir |
Refresh this wiki
This wiki was recently refreshed. Please wait 3 days to refresh again.