a-b-street/abstreet · error
to_geom called on a widget tree that has something…
Error message
to_geom called on a widget tree that has something interactive
What it means
`to_geom`/`consume_geometry` converts a widget tree into a plain GeomBatch for rendering; it only handles non-interactive widgets. Reaching any interactive widget (Button, Slider, etc.) in the tree is unsupported and panics.
Solutions
- Remove/replace interactive widgets before calling to_geom
- Only call to_geom on purely decorative trees (Labels, Lines, DeferDraw)
- Render interactive widgets normally via draw instead of extracting geometry
- Build a separate static tree for the geometry extraction
Example fix
// before panel.consume_geometry(&mut batch); // panel contains buttons // after let static_tree = Container::vertical(vec![Widget::draw_batch(label_batch)]); static_tree.consume_geometry(&mut batch);
Defensive patterns
Strategy: validation
Validate before calling
// ensure tree is non-interactive before extracting geometry
assert!(!panel.has_widget("save_btn"), "remove interactive widgets before to_geom"); Prevention
- Call to_geom only on decorative trees
- Build a separate static snapshot tree for exports
- Replace controls with their drawn geometry first
When it happens
Trigger: Calling `Panel::consume_geometry`/to_geom on a tree containing interactive widgets such as Buttons, Sliders, or TextBoxes.
Common situations: Trying to snapshot or export a Panel that still has controls on it; reusing an interactive Panel's contents as static drawing; forgetting to replace controls with a rendering of them first.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Don't know how to load
- Can't delete ; it's not in the World
- Can't delete mid-drag
- Dropdown has default_value , but none of the choices match…
- Failed to load svg from bytes. cache_key
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/b2b3fdd151394ee0.
Report an issue: GitHub.
Appendix: source
Thrown at widgetry/src/widgets/mod.rs:774
}
}
fn consume_geometry(mut self, batch: &mut GeomBatch) {
if let Some(bg) = self.bg_batch.take() {
batch.append(bg.translate(self.rect.x1, self.rect.y1));
}
if self.widget.is::<Container>() {
// downcast() consumes, so we have to do the is() check first
if let Ok(container) = self.widget.downcast::<Container>() {
for w in container.members {
w.consume_geometry(batch);
}
}
} else if let Ok(defer) = self.widget.downcast::<DeferDraw>() {
batch.append(defer.batch.translate(defer.top_left.x, defer.top_left.y));
} else {
panic!("to_geom called on a widget tree that has something interactive");
}
}
fn find(&self, name: &str) -> Option<&Widget> {
if self.id == Some(name.to_string()) {
return Some(self);
}
if let Some(container) = self.widget.downcast_ref::<Container>() {
for widget in &container.members {
if let Some(w) = widget.find(name) {
return Some(w);
}
}
}
None
}View on GitHub (pinned to 0964f29315)