$npx -y skills add flutter/agent-plugins --skill flutter-fix-layout-issuesFixes Flutter layout errors (overflows, unbounded constraints) using Dart and Flutter MCP tools. Use when addressing "RenderFlex overflowed", "Vertical viewport was given unbounded height", or similar layout issues.
| 1 | # Resolving Flutter Layout Errors |
| 2 | |
| 3 | ## Contents |
| 4 | - [Constraint Violation Diagnostics](#constraint-violation-diagnostics) |
| 5 | - [Layout Error Resolution Workflow](#layout-error-resolution-workflow) |
| 6 | - [Examples](#examples) |
| 7 | |
| 8 | ## Constraint Violation Diagnostics |
| 9 | |
| 10 | Flutter layout operates on a strict rule: **Constraints go down. Sizes go up. Parent sets position.** Layout errors occur when this negotiation fails, typically due to unbounded constraints or unconstrained children. |
| 11 | |
| 12 | Diagnose layout failures using the following error signatures: |
| 13 | |
| 14 | * **"Vertical viewport was given unbounded height"**: Triggered when a scrollable widget (`ListView`, `GridView`) is placed inside an unconstrained vertical parent (`Column`). The parent provides infinite height, and the child attempts to expand infinitely. |
| 15 | * **"An InputDecorator...cannot have an unbounded width"**: Triggered when a `TextField` or `TextFormField` is placed inside an unconstrained horizontal parent (`Row`). The text field attempts to determine its width based on infinite available space. |
| 16 | * **"RenderFlex overflowed"**: Triggered when a child of a `Row` or `Column` requests a size larger than the parent's allocated constraints. Visually indicated by yellow and black warning stripes. |
| 17 | * **"Incorrect use of ParentData widget"**: Triggered when a `ParentDataWidget` is not a direct descendant of its required ancestor. (e.g., `Expanded` outside a `Flex`, `Positioned` outside a `Stack`). |
| 18 | * **"RenderBox was not laid out"**: A cascading side-effect error. Ignore this and look further up the stack trace for the primary constraint violation (usually an unbounded height/width error). |
| 19 | |
| 20 | ## Layout Error Resolution Workflow |
| 21 | |
| 22 | Copy and use this checklist to systematically resolve layout constraint violations. |
| 23 | |
| 24 | ### Task Progress |
| 25 | - [ ] Run the application in debug mode to capture the exact layout exception in the console. |
| 26 | - [ ] Identify the primary error message (ignore cascading "RenderBox was not laid out" errors). |
| 27 | - [ ] Apply the conditional fix based on the specific error type: |
| 28 | - **If "Vertical viewport was given unbounded height"**: Wrap the scrollable child (`ListView`, `GridView`) in an `Expanded` widget to consume remaining space, or wrap it in a `SizedBox` to provide an absolute height constraint. |
| 29 | - **If "An InputDecorator...cannot have an unbounded width"**: Wrap the `TextField` or `TextFormField` in an `Expanded` or `Flexible` widget. |
| 30 | - **If "RenderFlex overflowed"**: Constrain the overflowing child by wrapping it in an `Expanded` widget (to force it to fit) or a `Flexible` widget (to allow it to be smaller than the allocated space). |
| 31 | - **If "Incorrect use of ParentData widget"**: Move the `ParentDataWidget` to be a direct child of its required parent. Ensure `Expanded`/`Flexible` are direct children of `Row`/`Column`/`Flex`. Ensure `Positioned` is a direct child of `Stack`. |
| 32 | - [ ] Execute Flutter hot reload. |
| 33 | - [ ] Run validator -> review errors -> fix: Inspect the UI to verify the red/grey error screen or yellow/black overflow stripes are resolved. If new layout errors appear, repeat the workflow. |
| 34 | |
| 35 | ## Examples |
| 36 | |
| 37 | ### Fixing Unbounded Height (ListView in Column) |
| 38 | |
| 39 | **Input (Error State):** |
| 40 | ```dart |
| 41 | // Throws "Vertical viewport was given unbounded height" |
| 42 | Column( |
| 43 | children: <Widget>[ |
| 44 | const Text('Header'), |
| 45 | ListView( |
| 46 | children: const <Widget>[ |
| 47 | ListTile(title: Text('Item 1')), |
| 48 | ListTile(title: Text('Item 2')), |
| 49 | ], |
| 50 | ), |
| 51 | ], |
| 52 | ) |
| 53 | ``` |
| 54 | |
| 55 | **Output (Resolved State):** |
| 56 | ```dart |
| 57 | // Wrap ListView in Expanded to constrain its height to the remaining Column space |
| 58 | Column( |
| 59 | children: <Widget>[ |
| 60 | const Text('Header'), |
| 61 | Expanded( |
| 62 | child: ListView( |
| 63 | children: const <Widget>[ |
| 64 | ListTile(title: Text('Item 1')), |
| 65 | ListTile(title: Text('Item 2')), |
| 66 | ], |
| 67 | ), |
| 68 | ), |
| 69 | ], |
| 70 | ) |
| 71 | ``` |
| 72 | |
| 73 | ### Fixing Unbounded Width (TextField in Row) |
| 74 | |
| 75 | **Input (Error State):** |
| 76 | ```dart |
| 77 | // Throws "An InputDecorator...cannot have an unbounded width" |
| 78 | Row( |
| 79 | children: [ |
| 80 | const Icon(Icons.search), |
| 81 | TextField(), |
| 82 | ], |
| 83 | ) |
| 84 | ``` |
| 85 | |
| 86 | **Output (Resolved State):** |
| 87 | ```dart |
| 88 | // Wrap TextField in Expanded to constrain its width to the remaining Row space |
| 89 | Row( |
| 90 | children: [ |
| 91 | const Icon(Icons.search), |
| 92 | Expanded( |
| 93 | child: TextField(), |
| 94 | ), |
| 95 | ], |
| 96 | ) |
| 97 | ``` |
| 98 | |
| 99 | ### Fixing RenderFlex Overflow |
| 100 | |
| 101 | **Input (Error State):** |
| 102 | ```dart |
| 103 | // Throws "A RenderFlex overflowed by X pixels on the right" |
| 104 | Row( |
| 105 | children: [ |
| 106 | const Icon(Icons.info), |
| 107 | const Text('This is a very long text string that will definitely overflow the available screen width and cause a RenderFlex error.'), |
| 108 | ], |
| 109 | ) |
| 110 | ``` |
| 111 | |
| 112 | **Output (Resolved State): |