flxzt/rnote · error
Building piet text layout failed, Err
Error message
Building piet text layout failed, Err: {e:?} What it means
build_text_layout uses a piet TextLayoutBuilder to lay out the text stroke; piet's build() returns a Result with a BuildError. Any layout failure (bad attributes, font issues, invalid ranges) is wrapped into this anyhow error. Callers like untransformed_size and cursor/selection APIs depend on it, so a failure here breaks all text measurement and editing.
Solutions
- Fix the root attribute error: ensure all font families in text_style resolve on this system
- Validate attribute ranges fit within the text length before building the layout
- Catch this error in callers and render fallback metrics or an error placeholder instead of propagating
- Verify fontconfig works (fc-list) on the target machine; install base fonts in containers/headless environments
Example fix
// before
let size = stroke.untransformed_size(&mut piet_cairo::CairoText::new(), text)?;
// after
let size = stroke.untransformed_size(&mut piet_cairo::CairoText::new(), text)
.with_context(|| format!("text layout failed for {:?}", stroke.text_style.font_attrs()))?; Defensive patterns
Strategy: try-catch
Validate before calling
// ensure all font families resolve before building
for attr in &stroke.text_style.attributes {
if let TextAttribute::FontFamily(f) = attr {
if piet_text.font_family(f.as_str()).is_none() { return Err(anyhow!("font '{f}' unavailable")); }
}
} Try / catch
let size = stroke.untransformed_size(&mut piet_cairo::CairoText::new(), text)
.context("text layout failed; check font availability and attribute ranges")?; Prevention
- Validate font families resolve before setting text attributes (see error 143)
- Keep attribute ranges within the text's byte length
- Install baseline fonts (fontconfig + DejaVu) in containers/headless environments
- Log the inner {e:?} BuildError — it names the exact failing attribute
When it happens
Trigger: Calling untransformed_size, lines, cursor_hittest_position, or get_selection_rects_for_cursors when the underlying layout build fails — typically because a TextAttribute references an unavailable font (see error 143) or an out-of-order/invalid range attribute.
Common situations: Text containing characters unsupported by the resolved font; attributes applied with ranges beyond text length; systems with broken fontconfig where piet cannot load any font.
Related errors
- query piet font family returned None for font family
- Building text layout failed, Err
- Make piet image in BitmapImage draw impl failed, Err
- finishing piet context failed, Err
- finishing piet context failed, Err
AI-assisted analysis of flxzt/rnote@bbc5354502 (2026-09-08).
Data as JSON: /api/errors/b016caf3c044b034.
Report an issue: GitHub.
Appendix: source
Thrown at crates/rnote-engine/src/strokes/textstroke.rs:284
let mut ranged_text_attributes = self.ranged_text_attributes.clone();
ranged_text_attributes.sort_unstable_by_key(|first| first.range.start);
// Apply ranged attributes
for (range, piet_attr) in ranged_text_attributes
.into_iter()
.filter_map(|ranged_attr| {
Some((
ranged_attr.range,
ranged_attr.attribute.try_into_piet(piet_text).ok()?,
))
})
{
text_layout_builder = text_layout_builder.range_attribute(range, piet_attr);
}
text_layout_builder
.build()
.map_err(|e| anyhow::anyhow!("Building piet text layout failed, Err: {e:?}"))
}
pub fn untransformed_size<T>(&self, piet_text: &mut T, text: String) -> anyhow::Result<Vector2>
where
T: piet::Text,
{
let text_layout = self.build_text_layout(piet_text, text)?;
let size = text_layout.size();
Ok(Vector2::new(size.width, size.height))
}
/// The cursors line metric relative to the textstroke bounds.
pub fn lines<T>(&self, piet_text: &mut T, text: String) -> anyhow::Result<Vec<piet::LineMetric>>
where
T: piet::Text,
{
let text_layout = self.build_text_layout(piet_text, text)?;
View on GitHub (pinned to bbc5354502)