Contents
- Constraint Model
- Error Signature Catalog
- Resolution Patterns
- Workflow: Fixing Layout Issues
- Examples
Constraint Model
Flutter layout operates on a strict negotiation rule:
Constraints go down. Sizes go up. Parent sets position.
- A parent widget passes constraints (min/max width and height) to its child.
- The child determines its own size within those constraints.
- The parent decides the child's position.
Layout errors occur when this negotiation fails — typically when a parent provides unbounded constraints (infinite width or height) and the child attempts to expand infinitely.
Error Signature Catalog
| Error Message | Root Cause | Quick Fix |
|---|---|---|
Vertical viewport was given unbounded height |
Scrollable (ListView, GridView) inside unconstrained vertical parent (Column) |
Wrap in Expanded or SizedBox(height: ...) |
An InputDecorator...cannot have an unbounded width |
TextField inside unconstrained horizontal parent (Row) |
Wrap in Expanded |
A RenderFlex overflowed by X pixels |
Child exceeds parent's allocated constraints | Wrap in Expanded, Flexible, or use overflow: TextOverflow.ellipsis |
Incorrect use of ParentData widget |
Expanded outside Flex, Positioned outside Stack |
Move widget to be direct child of correct parent |
RenderBox was not laid out |
Cascading error — look upstream in stack trace | Fix the primary constraint error above it |
Rule: Always fix the first error in the stack trace. RenderBox was not laid out is almost always a cascading side effect.
Resolution Patterns
Decision Tree
Error detected
├── Contains "unbounded height"?
│ └── Wrap scrollable child in Expanded or SizedBox
├── Contains "unbounded width"?
│ └── Wrap TextField/InputDecorator in Expanded
├── Contains "RenderFlex overflowed"?
│ ├── Text overflow?
│ │ └── Add overflow: TextOverflow.ellipsis + Expanded wrapper
│ └── Widget overflow?
│ └── Wrap in Expanded or Flexible
├── Contains "ParentData"?
│ └── Ensure Expanded is direct child of Row/Column/Flex
│ Ensure Positioned is direct child of Stack
└── Contains "RenderBox was not laid out"?
└── IGNORE — fix the error above this one
Expanded vs Flexible vs SizedBox
| Widget | Behavior | Use When |
|---|---|---|
Expanded |
Forces child to fill ALL remaining space | Child should stretch to fill |
Flexible |
Allows child to be SMALLER than remaining space | Child has natural size but shouldn't overflow |
SizedBox |
Provides absolute fixed constraints | You know the exact dimension needed |
ConstrainedBox |
Sets min/max constraints | You need bounded flexibility |
Workflow: Fixing Layout Issues
Task Progress
- Step 1: Run app in debug mode — capture the exact exception in console.
- Step 2: Identify the primary error message (ignore cascading
RenderBox was not laid out). - Step 3: Match error against the Error Signature Catalog above.
- Step 4: Apply the conditional fix:
- If
unbounded height→ wrap scrollable inExpandedorSizedBox - If
unbounded width→ wrap input inExpanded - If
RenderFlex overflowed→ wrap inExpandedorFlexible - If
ParentData→ restructure widget tree
- If
- Step 5: Hot reload → verify the error is resolved.
- Step 6: If new layout errors appear → repeat from Step 2.
Examples
Fixing Unbounded Height (ListView in Column)
Before (throws Vertical viewport was given unbounded height):
Column(
children: <Widget>[
const Text('Header'),
ListView(
children: const <Widget>[
ListTile(title: Text('Item 1')),
ListTile(title: Text('Item 2')),
],
),
],
)
After (resolved):
Column(
children: <Widget>[
const Text('Header'),
Expanded(
child: ListView(
children: const <Widget>[
ListTile(title: Text('Item 1')),
ListTile(title: Text('Item 2')),
],
),
),
],
)
Fixing Unbounded Width (TextField in Row)
Before (throws An InputDecorator...cannot have an unbounded width):
Row(
children: [
const Icon(Icons.search),
TextField(),
],
)
After (resolved):
Row(
children: [
const Icon(Icons.search),
Expanded(
child: TextField(),
),
],
)
Fixing RenderFlex Overflow (Text in Row)
Before (throws A RenderFlex overflowed by X pixels on the right):
Row(
children: [
const Icon(Icons.info),
Text('This is a very long text that will overflow the screen width'),
],
)
After (resolved):
Row(
children: [
const Icon(Icons.info),
Expanded(
child: Text(
'This is a very long text that will overflow the screen width',
overflow: TextOverflow.ellipsis,
),
),
],
)
Fixing ParentData Misuse
Before (throws Incorrect use of ParentData widget):
// Expanded must be a DIRECT child of Row/Column/Flex
Container(
child: Expanded( // WRONG: Expanded not inside a Flex
child: Text('Hello'),
),
)
After (resolved):
Row(
children: [
Expanded( // OK: Direct child of Row (a Flex widget)
child: Text('Hello'),
),
],
)
Source: dhruvanbhalara/skills — distributed by TomeVault.