a-b-street/abstreet · error

Initial panel outcome is

Error message

Initial panel outcome is {}. Consider calling ignore_initial_events

What it means

widgetry's Panel::build_custom runs the panel's event handler once inside a no-op event pass to initialize it. If the very first event already produces a non-Nothing Outcome (e.g. a button click or state change), the library panics, because a panel should not fire an action before the user interacts with it. The message suggests using ignore_initial_events to suppress that first outcome.

Solutions

  1. Pass ignore_initial_events: true to build_custom if the initial outcome is expected and harmless.
  2. Fix the widget so it produces Outcome::Nothing on its first (synthetic) event, e.g. skip processing until after initialization.
  3. Guard the widget's event handler against the initial no-op pass (check ctx.input state before emitting an outcome).

Example fix

// before
let panel = Panel::build(ctx, |panel, ctx| { ... });
// after
let panel = Panel::build_custom(ctx, |panel, ctx| { ... }, true /* ignore_initial_events */);
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure widgets emit Outcome::Nothing on the first event, or plan to use ignore_initial_events
let uses_ignore = true; // decide before building

Try / catch

// Since this panics (not a Result), avoid it by construction:
let panel = Panel::build_custom(ctx, |panel, ctx| { ... }, /* ignore_initial_events */ true);

Prevention

When it happens

Trigger: Calling Panel::build_custom with ignore_initial_events=false when the panel's initial layout or event handler immediately returns a non-Nothing Outcome (e.g. a checkbox whose initial state triggers a change, a button focused and activated during construction, custom widgets that emit outcomes in their first event call).

Common situations: Panels with widgets whose initial render triggers a click/change handler; custom Widgets implemented in a way that reacts to the synthetic initial event; recent refactors that added a widget whose initial event mutates state.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at widgetry/src/widgets/panel.rs:668

        // TODO: to support Panel's that can resize their `contents_dims`, we'll need to detangle
        // this dependency. This might entail decomposing the flexbox calculation to layout first
        // the inner content, and then potentially a second pass to layout any x/y scrollbars.
        panel.recompute_layout(ctx, false);
        panel.contents_dims =
            ScreenDims::new(panel.top_level.rect.width(), panel.top_level.rect.height());
        panel.update_container_dims_for_canvas_dims(ctx.canvas.get_window_dims());
        panel.recompute_layout(ctx, false);

        // Just trigger error if a button is double-defined
        panel.get_all_click_actions();
        // Let all widgets initially respond to the mouse being somewhere
        ctx.no_op_event(true, |ctx| {
            if ignore_initial_events {
                panel.event(ctx);
            } else {
                let outcome = panel.event(ctx);
                if !matches!(outcome, Outcome::Nothing) {
                    panic!(
                        "Initial panel outcome is {}. Consider calling ignore_initial_events",
                        outcome.describe()
                    );
                }
            }
        });
        panel
    }

    pub fn aligned(mut self, horiz: HorizontalAlignment, vert: VerticalAlignment) -> PanelBuilder {
        self.horiz = horiz;
        self.vert = vert;
        self
    }

    pub fn aligned_pair(mut self, pair: (HorizontalAlignment, VerticalAlignment)) -> PanelBuilder {
        self.horiz = pair.0;
        self.vert = pair.1;

View on GitHub (pinned to 0964f29315)