Skip to content

AI & TechnologyHow to Debug a Flutter and Firebase Bug: Find the Root Cause (2026)

Simon Dziak
Simon Dziak
Founder & developer, App369
LinkedIn
Published October 12, 2026 · Updated October 21, 2026Updated October 21, 2026Facts last verified October 21, 20269 min

Key takeaways

  • Write reproduction steps first: build number, device and OS, account or data, and exact taps. A bug you cannot reproduce cannot be verified as fixed.
  • Decide which layer fails (Flutter app, Firebase servers or build tooling) before changing code. Each has its own log, and the error is usually already in one of them.
  • Cloud Functions callables return only an INTERNAL error to the client unless the function throws an HttpsError, so read the function's own logs first.
  • Firestore reports a missing composite index in the error message, with a direct link to create it in the Firebase console.
  • Offline persistence is on by default on Android and Apple platforms and off on web, and a write's listener fires from the local cache immediately, so do not block the UI on the write.
  • Firebase Apple SDK 13 is no longer distributed through CocoaPods, and firebase_core 5.0.0 (October 15, 2026) builds on it, so CocoaPods fixes no longer apply to the newest plugins.

Pricing an app? Try the free app cost calculator or get a range for your project in the instant quote.

Most Flutter and Firebase bugs that take days to fix take days to find, not to fix. Once you can reproduce the bug on demand and you know which layer it lives in (the app, Firebase’s servers, or the build tooling), the fix is usually small. This guide is the order to work in, then the five problems that come up most.

It is the method behind App369’s fixed-price App Fix Ticket, and the one Simon uses on his own production Flutter and Firebase SaaS, Workspace369.

Step 1: Write down exact reproduction steps

Before reading any code, write the bug as steps someone else could follow:

  1. Which build: the app version, build number, and whether it is debug, profile or release.
  2. Which device and OS version, and whether it happens on web, iOS, Android or all three.
  3. Which account or data: a new user, an existing user, a specific record.
  4. The exact taps, and what you expected versus what happened.

If it only happens “sometimes”, note what the failing cases have in common: a slow network, a large account, the app coming back from the background. A bug you can’t reproduce can’t be verified as fixed.

Step 2: Find out which layer is failing

Each layer has its own log, and the error is usually already in one of them:

LayerWhere to look
Flutter appThe flutter run console or flutter logs, and Flutter DevTools for the widget inspector, logging, network and memory views
Release builds in users’ handsFirebase Crashlytics for Flutter for crashes and non-fatal errors you record. Set FlutterError.onError to FirebaseCrashlytics.instance.recordFlutterFatalError and PlatformDispatcher.instance.onError to call FirebaseCrashlytics.instance.recordError(error, stack, fatal: true); use recordError without fatal for caught errors
Cloud FunctionsLogs Explorer in the Google Cloud console, or firebase functions:log
Firestore and StorageThe exact error code your app receives, such as permission-denied or failed-precondition
Build toolingThe full output of flutter build with -v, plus Xcode or Gradle’s own logs

A Firestore permission-denied error means Security Rules refused the request; it is not an app crash. If the opposite worries you, that rules allow too much, paste them into the free Firebase rules checker. A failed-precondition error on a query often includes a link to create the missing index. Read the full message before changing code.

Step 3: Isolate it with the Emulator Suite

The Firebase Local Emulator Suite runs Auth, Firestore, Functions and Storage on your machine. Point a debug build at the emulators, load the data that triggers the bug, and you can repeat the failing steps as often as you need without touching production data. Security Rules problems in particular are easier to see in the Emulator UI’s Firestore Requests view, which lists each request and shows how your rules evaluated it.

The five issues that come up most

Build failures

  • Run flutter doctor -v first. It catches missing toolchains, licenses and Xcode or Android SDK problems.
  • For iOS, check that your app targets iOS 15 or later, which Firebase Apple SDK 13 requires. Firebase 13 and later are no longer distributed through CocoaPods, and firebase_core 5.0.0 builds on Firebase Apple SDK 13, so use Swift Package Manager, which Flutter 3.44 and later turn on by default (if you turned it off, run flutter config --enable-swift-package-manager), and check the Xcode build log for Swift package resolution errors. If you are still on an older FlutterFire release that uses CocoaPods, run pod repo update and pod install in the ios folder.
  • For Android, check that the Android Gradle Plugin, Gradle and Kotlin versions are compatible with each other, and that minSdk meets your plugins’ minimum (firebase_core 5.0.0 requires 24). If the build broke right after moving to AGP 9, see how to fix a Flutter Android build after AGP 9.
  • After upgrading Flutter or the FlutterFire plugins, upgrade all FlutterFire plugins together; mixed versions are a common cause of build errors. The October 2026 FlutterFire release is a major version (firebase_core 5.0.0), with breaking changes to the native SDK versions, so read each plugin’s changelog before upgrading.

Login loops

A user signs in and lands back on the sign-in screen, or the app flickers between screens. The usual causes:

  • The router redirects before Firebase Auth has restored the session. On a cold start, authStateChanges() emits once the saved user is loaded; decide the first screen after that first event, not before.
  • Redirect logic that reads two different sources of truth, such as the auth state and a user profile document that hasn’t loaded yet.
  • On web, the redirect sign-in flow returning to a page that immediately redirects again.

Firestore writes that hang

A set() or update() call whose Future never completes is often not stuck at all. With offline persistence, which is on by default on Android and iOS (and off by default on web), the write is applied to the local cache immediately, and the Future completes only when the server confirms it. On a poor connection or with no connection, that can take a long time. Don’t block the UI on the Future: let the snapshot listener show the change. If the write is rejected, the Future completes with an error such as permission-denied, so make sure something catches and reports it.

Cloud Function errors

  • Read the function’s own logs before the client error; the client often only receives internal.
  • In callable functions, throw an HttpsError with a clear code and message, so the app can show a useful error instead of a generic one.
  • Check the function’s region in the app matches where it is deployed.
  • For timeouts, compare the configured timeout and memory with what the function actually does.

A broken screen

A red error screen in debug, or a grey one in release, means an exception was thrown during build. The console shows the first exception; fix that one first, because later errors are often caused by it. Common causes are a null value from a document field that doesn’t exist on older records, and a list or column without bounded height inside a scrolling parent.

Fix it with a test

When you’ve found the root cause, write a test that fails because of it, then make it pass. Widget tests cover screens and state; the Firebase emulators let integration tests and Security Rules tests run against real Firebase behavior. The test keeps the bug from coming back in the next release.

When to get help

If a bug has eaten more than a day, App369 offers a fixed-price App Fix Ticket. The $450 Diagnosis delivers the root cause with evidence and a fixed repair quote within 3 business days, and the $450 is credited toward the fix. The $1,200 Fix delivers one scoped defect fixed as a pull request, with a regression test and handover notes, within 5 business days. If the problem turns out to be your Security Rules, the Firebase Security Rules guide is a good next read.

Want this done at a fixed price?

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

Frequently asked questions

Why does my Firestore write never finish?
With offline persistence, a write is saved to the local cache at once and your snapshot listeners fire immediately, but the write is only confirmed once the backend accepts it. On a slow or missing connection that can take a long time. Show the change from your snapshot listener instead of waiting on the write, check hasPendingWrites, and catch errors such as permission-denied.
Why does my Flutter app keep returning to the login screen?
Usually because the router decides where to go before Firebase Auth has restored the saved session, or because redirect logic depends on data that has not loaded yet. Firebase fires an authStateChanges event after the stored credentials are restored, so choose the first screen after that first event.
How do I see Cloud Functions errors?
Run firebase functions:log, or use Logs Explorer in the Google Cloud console. A callable function that throws anything other than an HttpsError gives the client only an INTERNAL error, so the function's own logs hold the real message.
Can I debug Firebase without touching production data?
Yes. The Firebase Local Emulator Suite runs Auth, Firestore, Functions and Storage on your machine. Load test data that reproduces the bug and point a debug build at the emulators. The Firestore Requests view in the Emulator UI shows how your Security Rules evaluated each request.
How do I log errors from a release build with Crashlytics?
Add firebase_crashlytics and run flutterfire configure. In main, set FlutterError.onError to FirebaseCrashlytics.instance.recordFlutterFatalError and PlatformDispatcher.instance.onError to call FirebaseCrashlytics.instance.recordError with fatal: true. Use recordError without fatal for errors you catch yourself.
Why did my iOS build break after upgrading FlutterFire?
Firebase Apple SDK 13 is no longer distributed through CocoaPods and requires iOS 15 or later. firebase_core 5.0.0 builds on it, so a CocoaPods-only setup may fail. Use Swift Package Manager, which is on by default since Flutter 3.44, and read the plugin changelogs before upgrading.
What should I send a developer to fix a Flutter bug?
Exact reproduction steps, the app version and build number, the device and OS, the error message or a screen recording, and access to the repository. With those, a developer can usually reproduce the bug on the first try.

Sources

  1. Firebase docs, Get started with Firebase Crashlytics (Flutter)
  2. Flutter docs, Handling errors in Flutter
  3. Firebase docs, Access data offline (Cloud Firestore)
  4. Firebase docs, Call functions from your app (callable errors)
  5. Firebase docs, Write and view logs (Cloud Functions)
  6. Firebase blog, Meet the Firestore Emulator Requests Monitor
  7. Firebase Apple SDK release notes (13.0.0, CocoaPods distribution ends)
  8. pub.dev, firebase_core changelog (5.0.0)
Tags
#flutter debugging #firebase debugging #flutter build failure #firebase auth #firestore #cloud functions errors
Share:

Related Resources

Related guides