Flutter / Editorial solution guide

Diagnose an unbounded list and a flex overflow

Find the first contradictory constraint in a search page instead of stacking unrelated layout patches.

About 3 min readContent reviewed

Read-only knowledge base · No public comments

Recognize the symptoms

A search page reports an unbounded vertical viewport, or a long translated row displays a RenderFlex overflow. The first exception appears during layout; later paint errors may follow.

The page contains a header, filters, and a result list. Adding a fixed height appears to help one screen size but fails when the keyboard or large text reduces usable space.

Understand the likely causes

  • A scrollable was asked to determine its own height inside an unbounded vertical parent, or a flex child was asked to divide infinite remaining space.
  • Separately, a Row may give a non-flex text child insufficient width discipline. Similar visual symptoms can come from different axes and require different fixes.

Preserve the first relevant failure

Capture the first layout exception and a minimal synthetic widget tree. Identify the failing axis and the nearest ancestor expected to provide a finite bound. Remove unrelated data loading from the reproduction so timing and transport failures do not obscure the constraint problem. Record window size, text scale, direction, and keyboard visibility. An error naming a vertical viewport points to height ownership; a horizontal RenderFlex overflow points to main-axis content allocation. Do not treat every later paint failure as an independent root cause.

Choose one page scrolling contract

Decide whether the header stays fixed while results scroll or whether the entire page scrolls together. For the fixed-header case, a bounded Scaffold body can contain a Column with the list inside Expanded. For a continuous page, use an appropriate single scrolling composition, potentially with slivers. Wrapping that same Expanded Column in a vertical scroll view creates an incompatible height contract. shrinkWrap changes sizing work and is not a universal performance-neutral cure for nested scrolling. Choose it only when the intended small-content sizing contract warrants it.

Bound the result viewport explicitly

The fragment illustrates a fixed heading and a remaining-height list. It assumes the enclosing body receives finite height. Use local synthetic rows while verifying the layout; no backend is needed. If the page must also contain dynamic filters, include their expanded height in tests rather than replacing them with a constant spacer. The important fact is that Expanded receives a finite remainder from the bounded Column. This does not mean every nested list in every context should be wrapped in Expanded.

dart Illustrative Dart or Flutter fragment; requires the declared SDK host.
Widget resultBody() => Column(children: [
  const Text('Results'),
  Expanded(child: ListView.builder(
    itemCount: 30,
    itemBuilder: (_, index) => ListTile(title: Text('Result ${index + 1}')),
  )),
]);
Expected output
A fixed heading sits above a bounded, scrollable result list.

Requires a Flutter Material host with finite body height. The fragment was not executed with an SDK.

Repair row width as a separate problem

If the list now lays out but one translated row still overflows, inspect that row’s horizontal constraints separately. Give the text an appropriate flex allocation beside fixed controls and choose wrapping or truncation according to information importance. Preserve essential identifiers through a detail or copy action if truncation would make them ambiguous. Test logical start/end padding for Arabic and verify large text does not make the primary action unreachable. A fixed-height row may need to grow even after the text has a valid width.

Verify the fix

Repeat the minimal case with empty data, thirty rows, a long Arabic label, large text, and the keyboard visible. Verify scrolling reaches the final row and no first layout exception remains.

A JSON or source inspection cannot establish device layout behavior. Run these checks in the project’s compatible Flutter host and record the target and dimensions actually exercised.

Keep it from recurring

  • Document which widget owns scrolling and which ancestor supplies each finite bound. Keep long and scaled text in routine layout review, and preserve a small regression fixture for the repaired structure.

Official references