Flutter Deep Dive Part 1: “RenderFlex children have non-zero flex…
This article is part of a four-part series. You can find the others here:
- Part 1: “RenderFlex children…”, wading into the Baby Pool
- Part 2: Taking the Plunge
- Part 3: A Flex is not a flex
- Part 4: The Flex Layout Algorithm
In addition to speaking about Flutter and embarrassing myself in front of audiences on two continents, I recently decided to do a deep dive. All of my friends do deep dives on cool things like Animation, State Management, Gestures or Testing.
Me? I decided to do a deep dive on an error message.
But this is no ordinary error message. If InheritedWidget
is Flutter’s Monad (and it is), then “RenderFlex children have non-zero flex but incoming height constraints are unbounded” is our Boogeyman (Uomo Nero, Бугимен, Hombre Boogeyman, بعبع , Mumus, Croque-mitaine, Baba Yaga, John Wick).
It should also be noted that our Boogeyman has a few brothers and sisters you might see now and then:
- “RenderConstrainedBox object was given an infinite size during layout.”
- “BoxConstraints forces an infinite width.”
- And more you’ll be able to recognize after you‘ve read this deep dive.
Relax, all of these errors are nothing more than small variations on a single theme. The error messages are different because in each of these cases the error is being caused by something different but, in the end, it all boils down to the same problem:
Something is trying to be infinitely large, nothing is there to stop it, and you need to fix that.
Once you understand the way things work under the hood, it gets easier and easier to know exactly what to do when the Boogeyman crawls out from under your bed.
You send John Wick, of course.
Wading Into the Baby Pool
First I want to offer a quick version of this for those who don’t want to dive into deep water. I call it, “The Baby Pool Version”.
Please note that all these code examples are custom formatted to be a little easier to read. I don’t format my working code like this…
“RenderFlex children have non-zero flex but incoming height constraints are unbounded.”:
This is a simple example of a broken widget that will cause this error:
What’s happening here is a Row/Column
is not being passed size constraints by its parent (“Incoming Constraints are Unbounded”) but its child is trying to “flex” to be as big as possible (“Render Flex Children Have Non-Zero Flex”). The reason this is a problem is that either the parent or child has to tell the Row/Column
what size to be, but that’s not happening. The child is saying, “Go to infinity”, and the parent is saying, “Do whatever you want”.
The quick, baby pool fix is to change the mainAxisSize
of theRow/Column
to MainAxisSize.min
, then wrap the child that wants to be infinitely large in an Expanded
.
“BoxConstraints forces an infinite height (or width).”:
Your Row/Column
has a child that is trying to be infinite height/width and there aren’t any constraints, which is only a slightly different situation than the one above. One way this can happen is if you set the height/width
to double.infinity
on something that is inside of a Row/Column
. That’s not a bad thing, we do it all the time. However, if your child is in a Row
or Column
that isn’t limiting the child’s size, now we have problems.
This error can be in the mainAxis
or the crossAxis:
- If the problem is in the
mainAxis
you can fix it by putting the offending child inside of anExpanded
. - If it’s along the
crossAxis
and you nestedRows
andColumns
inside of each other, then you need to put the nestedRow/Column
into anExpanded
instead.
“RenderConstrainedBox object was given an infinite size during layout.”:
This one is kind of cute. I forced it to happen like this:
How do we deal with this? Well, there are a few things you might try, but not all of them would be successful:
- Giving the
Container
a specific height will fix it. - Giving the
SizedBox
a specific height will fix it. - Wrapping the
Container
with anExpanded
will not fix it. That actually causes a bottom overflow. - Wrapping the
SizedBox
with anExpanded
will cause: “Incorrect use of ParentDataWidget.Expanded
widgets must be placed directly insideFlex
widgets.”
The last error, the one about ParentDataWidget? It means an Expanded
can only be used inside of a Row
or Column
but you tried to use it somewhere else.
So, that was the baby pool. Wasn’t that easy?
Ready for more? Are you feeling adventurous… or maybe just masochistic? Then let’s go a little further down the rabbit hole with Part 2!
You can stalk the author on Twitter at https://twitter.com/scottstoll2017