slint-ui/slint · critical
fatal: swash is unable to parse truetype font
Error message
fatal: swash is unable to parse truetype font
What it means
`get_swash_font_info` parses a fontique font blob with `swash::FontRef::from_index` and panics if swash cannot parse the data as a TrueType/OpenType font. The software renderer assumes every font the system font enumeration (fontique) returns is parseable; a corrupt, DRM-protected, or non-TrueType font file breaks that assumption. The `or_insert_with` cache means the panic happens once per (blob, index) pair, on first use.
Solutions
- Find and remove/repair the corrupt font file (validate all fonts with e.g. `fonttools ttx <file>` or `fc-validate`)
- Clear font caches (`fc-cache -f`) after fixing fonts so fontique re-enumerates clean data
- Restrict the fonts available to the app (point `FONTCONFIG_FILE`/`XDG_DATA_HOME` at a curated font dir with a known-good font like DejaVu)
- Update Slint/fontique/swash — newer versions may skip unparsable fonts instead of panicking
Example fix
// validate fonts before shipping an embedded system image // before: broken-font.ttf present in the font dir $ fonttools ttx broken-font.ttf # fails => remove it $ fc-cache -f // after: only valid fonts in the font directory $ ls fonts/ # DejaVuSans.ttf, Roboto-Regular.ttf ...
Defensive patterns
Strategy: fallback
Validate before calling
// validate font files at deploy time $ fonttools ttx font.ttf # or: fc-validate --all
Prevention
- Ship a curated, validated font set (e.g. DejaVu, Noto) instead of system font dirs
- Run `fc-cache -f` and validate fonts in CI for embedded images
- Sanitize user-supplied font directories before pointing fontique at them
- Update Slint/fontique/swash so unparsable fonts are skipped rather than panicking
When it happens
Trigger: Text rendering via the software renderer when a font selected by fontique for the query cannot be parsed by swash: broken/corrupted font files in font directories, fonts with unsupported formats (Type 1, bitmap-only), or an out-of-range `index` into a font collection (TTC) blob.
Common situations: Linux systems with damaged fonts in `~/.fonts` or `/usr/share/fonts`; containers/minimal images with malformed font packages; custom font loading via `slint::platform::software_renderer` where a bad `.ttf`/`.ttc` is registered; font collections where the requested index is out of bounds.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- No font fallback found. The software renderer requires…
- large glyph x coordinate
- large glyph y coordinate
- large width
- a setter belongs to a field
AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16).
Data as JSON: /api/errors/0138368d8246d3f9.
Report an issue: GitHub.
Appendix: source
Thrown at internal/renderers/software/fonts/systemfonts.rs:30
use super::super::PhysicalLength;
use super::vectorfont::VectorFont;
struct CachedFontInfo {
swash_key: swash::CacheKey,
swash_offset: u32,
}
i_slint_core::thread_local! {
// swash font info cached and indexed by fontique blob id (unique incremental) and true type collection index
static SWASH_FONTS: RefCell<HashMap<(HashedBlob, u32), CachedFontInfo>> = Default::default();
}
pub fn get_swash_font_info(blob: &fontique::Blob<u8>, index: u32) -> (swash::CacheKey, u32) {
SWASH_FONTS.with(|font_cache| {
let mut cache = font_cache.borrow_mut();
let info = cache.entry((blob.clone().into(), index)).or_insert_with(move || {
let font_ref = swash::FontRef::from_index(blob.data(), index as usize)
.expect("fatal: swash is unable to parse truetype font");
CachedFontInfo { swash_key: font_ref.key, swash_offset: font_ref.offset }
});
(info.swash_key, info.swash_offset)
})
}
fn get_swash_font_info_for_query_font(font: &fontique::QueryFont) -> (swash::CacheKey, u32) {
get_swash_font_info(&font.blob, font.index)
}
pub fn match_font(
request: &super::FontRequest,
scale_factor: super::ScaleFactor,
collection: &mut fontique::Collection,
source_cache: &mut fontique::SourceCache,
) -> Option<VectorFont> {
if request.family.is_some() {
let requested_pixel_size: PhysicalLength =View on GitHub (pinned to bb937076de)