Skip to content

Per-view widget layout budget (1024 nodes) drops whole frames on real multi-pane app views #408

Description

@slicenferqin

Symptom

A production three-pane desktop app built on the SDK hits WidgetLayoutListFull on ordinary interactions. The layout-retention failure drops the whole frame: opening a dialog, or clicking controls in a large view, leaves the UI visually unchanged — buttons appear dead. Once a view is over budget, the error fires on every invalidated frame, wedging the view's interactions entirely.

Evidence

View composition (real app, nothing exotic):

  • a session rail enumerating ~50 session rows,
  • a detail timeline retaining the full transcript,
  • a model-picker dialog listing ~60 model rows with provider-group headers.

Automation snapshot of the dialog frame: 1008 widgets. The retained node count runs ≈1.8 nodes per widget (each row widget carries inner rows/columns/text), so the frame needs ~1800 nodes — well past the 1024 cap in canvas_limits.max_canvas_widget_nodes_per_view. The error path is adoptWidgetLayoutWidgetLayoutListFull → the rebuild never lands and the whole frame is discarded.

The current comment sizes 1024 against "the measured worst realistic three-pane view is ~500 nodes". That estimate predates list-dense surfaces: any app whose rails/dialogs enumerate unbounded collections (sessions, models, files) crosses 1024 with a single dialog open on top of the base chrome. The failure mode is much worse than the budget's "fail loudly" intent — it doesn't reject an operation, it silently kills every subsequent frame for the view.

Proposed fix

Raise the budget 1024 → 4096 (and automation.snapshot.max_widgets_per_view in lockstep; the existing lockstep test in canvas_widget_layout_tests.zig keeps them equal). These are validation bounds over fixed-capacity address space — pages are only touched as views use capacity — so the raise costs address space, not committed memory. PR to follow.

Longer term, apps retaining unbounded collections will outgrow any fixed cap; windowed/virtualized retention for list widgets would remove the cliff entirely. Happy to file a separate issue for that discussion if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions