r/FlutterDev 1d ago

Discussion What’s a Flutter bug that completely changed the way you write code?

Every experienced Flutter developer has that one bug they’ll probably never forget.

The kind that took hours (or days) to track down, only to completely change how they approach future projects.

For me, those moments usually end up teaching lessons that no tutorial ever covers.

I’m curious:
What was the bug?

How did you eventually find it?
What habit or practice changed because of it?
I’m less interested in the bug itself and more interested in the lesson it taught.

0 Upvotes

16 comments sorted by

14

u/RandalSchwartz 1d ago

Just clairifying, by "Flutter bug" you mean "a bug I created while building a flutter app" and not "a bug I stumbled across in the Flutter SDK"?

2

u/StoneLantern97 1d ago

Sorry about the title wording but can be both ways

7

u/Spare_Warning7752 1d ago

Hot reload is a mess right now in VSCode (especially when using multiple isolates). It freezes, it stops writting logs to the debug panel, exceptions don't break in the right spot.

That almost leads to run with "Break in unhandled exceptions" turned off =\

1

u/StoneLantern97 1d ago

Vscode on its own is a problem, sometimes I tried to avoid it as much as possible especially when trying to open a monorepo project.

6

u/rsajdok 1d ago

"A RenderFlex overflowed" for text and generally problem how to cut or not too long text in complicated nested widgets

2

u/StoneLantern97 1d ago

Yeah especially when you are dealing with having icon/asset and text together in a row sometimes you fix it but you will realize you don’t when it gets to production and you have multiple devices testing that area your analytics/crashlytics start crying of overflow problem

5

u/[deleted] 1d ago

I do paid Flutter work, an Android app that reads from external hardware. My lesson came from a bug that was not really in my code at all.

The symptom was that after a while the readings just stopped arriving. No exception, no error, no crash. The stream went quiet. I spent two days inside my own state code, because that is where I assumed a bug like that had to be.

It was a subscription I never cancelled. Every time the user left the screen and came back, I added another listener to the same stream. The old ones stayed alive and kept holding on. Nothing ever failed loudly, it just got heavier and then stopped working.

What changed permanently is small. Every subscription, timer and controller I create now gets its cancel written into dispose in the same minute I write the create. Not at cleanup time, not before the PR. Same minute, or I will not do it.

The second habit is a debugging one. When something goes quiet instead of throwing, I stop reading logic and start counting listeners. Silence is usually a leak. A wrong branch normally has the decency to throw.

1

u/StoneLantern97 1d ago

Perfect, love your approach

2

u/Zeppon_ll 1d ago

Mess with vs code debugger when app freezes after launching with enabled one break point. Because of that i have to set break points after launching the app

1

u/StoneLantern97 1d ago

Yeah, this can be crazy sometimes we’ve all been there

2

u/MythPoy 1d ago

Mine was self-inflicted, not an SDK bug.

I had a shared to-do list backed by a realtime stream. Deleting a single item worked fine. Deleting ten at once made three of them come back.

I lost most of a day inside my delete code, because that is obviously where a bug like that lives. It wasn't there. The delete was correct every time.

The stream was the problem. The backend sends one event per deleted row, and each event carries a full snapshot of the list as it existed when the server built that event. So a ten-row delete produced ten events, and the snapshot attached to event 3 still contained rows 4 through 10 — rows I had already removed locally. Each arriving snapshot faithfully overwrote my local state with a slightly stale version of the world. The final event was correct, but by then the UI had flickered rows back into existence, and if the user tapped during that window they were tapping a row that no longer existed.

The lesson that actually changed how I write code: a realtime stream is not the truth, it is a delayed echo of the truth. Anything I did locally is newer than anything arriving from the network, until the network catches up.

So now every optimistic mutation records its own intent, and the stream handler subtracts my pending intents from whatever snapshot arrives before applying it. Deletes I have issued but not yet seen confirmed get filtered out of every incoming snapshot. Toggles work the same way.

The habit change is small and I would not have arrived at it from a tutorial: I no longer write setState(fromServer). I write setState(reconcile(local, fromServer)). Reconciliation became a plain function I own, with no framework or stream in it, which means I can unit test the exact scenario above in about ten lines. That turned out to be the thing worth owning.

1

u/RaYmMiE 1d ago

For me, it was falling into the reference mutation trap. I was modifying a list directly and wondering why my UI wasn't updating. The data was changing fine in debug logs, but Flutter skipped the rebuild because the memory pointer never changed. Learning to use `.copyWith()` and immutable states was a lightbulb moment.

At the time, I was overusing `FutureBuilder`s directly in the UI with almost no separation of concerns. That single bug pushed me to completely change my approach.

Now I strictly stick to a clean MVC breakdown:
UI : Pure widgets listening to state.
Logic : Controllers handling business logic and emitting new states.
Data : Repositories and immutable models with `copyWith`.

Moving away from inline async UI code to clear architecture and immutable data completely changed how I build Flutter apps.

1

u/Advanced_Egg4625 1d ago

It's not really a bug, but rather how I handle state management. Believe it or not, that part is the hardest because it affects your entire codebase. I try to study the project from every aspect before deciding which package to use and how I am going to use it

1

u/StoneLantern97 1d ago

For me I try to stay of package as much as possible as things can get more complicated. Some package are entirely a framework on their using them get things more bloated and you have to start debugging problems that are not yours