a-b-street/abstreet · error

Can't take( ), it's a top-level widget

Error message

Can't take({}), it's a top-level widget

What it means

`take` removes a nested named widget from a Panel's tree and returns it, but the top-level widget itself cannot be removed without destroying the Panel. Panics if the requested name matches the top-level widget.

Solutions

  1. Use a child/container widget name, not the root's name
  2. If you need to replace the whole content, use replace or set_content instead of take
  3. Check with has_widget and ensure the target is nested
Defensive patterns

Strategy: validation

Validate before calling

if panel.has_widget(name) && name != ROOT_NAME { /* take is safe to attempt */ }

Prevention

When it happens

Trigger: Calling `Panel::take(name)` where `name` is the id of the Panel's top-level (root) widget.

Common situations: Assuming take works on any named widget including the root; passing the panel's own name because it was set via `.named(...)` on the root.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/ea26a3f4b71ad976. Report an issue: GitHub.

Appendix: source

Thrown at widgetry/src/widgets/mod.rs:811

    fn find_mut(&mut self, name: &str) -> Option<&mut Widget> {
        if self.id == Some(name.to_string()) {
            return Some(self);
        }

        if let Some(container) = self.widget.downcast_mut::<Container>() {
            for widget in &mut container.members {
                if let Some(w) = widget.find_mut(name) {
                    return Some(w);
                }
            }
        }

        None
    }

    fn take(&mut self, name: &str) -> Option<Widget> {
        if self.id == Some(name.to_string()) {
            panic!("Can't take({}), it's a top-level widget", name);
        }

        if let Some(container) = self.widget.downcast_mut::<Container>() {
            let mut members = Vec::new();
            let mut found = None;
            for mut widget in container.members.drain(..) {
                if widget.id == Some(name.to_string()) {
                    found = Some(widget);
                } else if let Some(w) = widget.take(name) {
                    found = Some(w);
                    members.push(widget);
                } else {
                    members.push(widget);
                }
            }
            found
        } else {
            None

View on GitHub (pinned to 0964f29315)