in

How to Fix Google Play Console “App Bundle contains native code” Warning Without Changing Code Architecture

Uploaded a Flutter build to internal testing a while back and got hit with the classic “This App Bundle contains native code, and you’ve not uploaded debug symbols” warning. First reaction was mild panic — did I accidentally pull in some native dependency I didn’t mean to? Nope. Every Flutter app hits this because the engine itself ships native libraries. So let’s get into what this warning actually means and how to clear it without touching your architecture at all.

Quick Answer

  • This warning doesn’t mean something’s wrong with your app — it means your app ships native .so libraries and Play Console can’t symbolicate crash reports from them yet
  • <cite index=”106-1″>If your project builds an Android App Bundle, you can configure your build to automatically include the native debug symbols file so it’s uploaded to Play Console when you publish</cite>
  • The fix is almost always a one-line Gradle setting, not a code or architecture change
  • Flutter, React Native, and any app using NDK or third-party native libraries (ARCore, camera SDKs, ML libraries) will see this by default
  • You do not need to remove native dependencies to clear this warning — that would be solving a problem you don’t have

Why It Fails

This warning shows up because your app bundle contains compiled native code — .so files — and Google Play doesn’t have the matching debug symbol information to turn a crash’s raw memory addresses back into readable function names and line numbers.

A few things cause this specifically:

Framework-level native libraries you didn’t add yourself. Flutter ships its own native engine libraries in every release build. React Native, along with plenty of camera, ML, and AR SDKs (ARCore is a common one), does the same. <cite index=”96-1″>Even ARCore-based apps commonly trigger this exact warning</cite>, and it has nothing to do with anything the developer wrote directly.

Debug symbols get stripped by default during release builds. Android’s build process strips symbol information from native libraries in release configuration to keep file size down. That’s normal and correct behavior — the problem is only that Play Console wants a copy of the unstripped version separately, and by default nothing tells Gradle to produce or package it.

Older Android Gradle Plugin versions handling this differently. <cite index=”110-1″>If you’re on Android Gradle plugin version 4.1 or later, you can have the debug symbols automatically included in the app bundle, but earlier versions need a different, more manual process</cite>, which is where a lot of the confusion in forum threads comes from — people following instructions for the wrong AGP version.

Third-party plugins or libraries bundling their own native code silently. Sometimes it’s not your core framework at all — a single dependency deep in your pubspec.yaml or build.gradle can pull in native code you weren’t tracking, and the warning is the first time you find out about it.

The thing people get wrong most often: they assume this warning means they need to remove native dependencies or restructure their app to avoid using native code entirely. <cite index=”107-1″>That’s not accurate — uploading the debug symbol file isn’t optional if you care about debugging crashes effectively, but it’s a packaging step, not an architectural one.</cite>

Technical Comparison Table

ApproachEffortBest for
debugSymbolLevel = 'FULL' in build.gradleLow, one lineMost apps, gives full file/line info
debugSymbolLevel = 'SYMBOL_TABLE' in build.gradleLow, one lineApps hitting size limits, function names only
Manual zip upload of merged native libsMediumOlder AGP versions, one-off releases
Ignoring the warning entirelyNoneApps you don’t plan to debug crashes on — not recommended

Step-by-Step Fixes

Step 1: Confirm your Android Gradle Plugin version

Check your project’s build.gradle (project level) or gradle-wrapper.properties for the AGP version. <cite index=”106-1″>If you’re on a version that supports automatic inclusion, the Gradle setting approach below will work directly.</cite>

Step 2: Add the debug symbol level setting

In your app-level build.gradle (or build.gradle.kts for Kotlin DSL):

gradle

android {
    buildTypes {
        release {
            ndk {
                debugSymbolLevel 'FULL'
            }
        }
    }
}

<cite index=”106-1″>Use SYMBOL_TABLE to get function names in symbolicated stack traces, or FULL to get function names, files, and line numbers.</cite> FULL is more useful for debugging but produces a noticeably larger file.

Step 3: Rebuild your release bundle

flutter build appbundle --release

Or for a plain Android project, use your usual release build command through Gradle or Android Studio’s Generate Signed Bundle flow.

Step 4: Check the bundle size limit

<cite index=”106-1″>There’s a 1.6 GB limit for the native debug symbols file. If your debug symbols footprint is too large, use SYMBOL_TABLE instead of FULL to bring the size down.</cite> This is rarely an issue for smaller apps but worth knowing about if you’re bundling a lot of native libraries.

Step 5: If it still doesn’t include automatically, upload manually

<cite index=”105-1″>Navigate to your project’s merged native libs output directory, find the ABI folders inside, select all of them, and create a zip file.</cite> Then upload that zip through Play Console under App bundle explorer > Native debug symbols.

Step 6: Re-upload and verify the warning clears

Upload the new bundle to any testing track. The warning should no longer appear on that specific release. Note that it’s per-version — you’ll need this configured for every future release build too, not just a one-time fix.

What Actually Worked For Me

My first instinct, embarrassingly, was to start looking at which dependency was pulling in native code so I could maybe swap it out. That’s backwards thinking entirely — I was trying to solve a problem (“my app has native code”) that isn’t actually a problem at all for a Flutter app. Wasted a chunk of time going down that path before it clicked.

The actual fix took about two minutes once I stopped overthinking it: added the debugSymbolLevel 'FULL' line to build.gradle, rebuilt, uploaded, warning gone. From what I’ve seen since across a few different projects, this covers the vast majority of cases — the manual zip upload route is really only necessary on older toolchains or in edge cases where the automatic inclusion just doesn’t trigger for some reason nobody’s fully documented well.

Advanced Fixes and Edge Cases

Check for build cache issues if the setting doesn’t seem to take effect. Sometimes a stale Gradle cache holds onto an old build configuration. Running a clean build (flutter clean then rebuild, or Gradle’s clean task) before generating the bundle again resolves cases where the setting is correctly in place but doesn’t seem to apply.

Verify your NDK version is compatible. Very old or very new NDK versions occasionally have quirks with symbol generation. <cite index=”108-1″>Checking your installed NDK version through SDK Manager and pinning a specific known-working version in your build.gradle can resolve edge cases where the default toolchain version behaves inconsistently.</cite>

Consider whether you need FULL or SYMBOL_TABLE based on actual debugging needs. If you’re mostly relying on Play Console’s own crash reporting and not doing deep native-level debugging, SYMBOL_TABLE keeps your bundle smaller while still giving you function names in crash traces — a reasonable trade-off for a lot of apps.

Check third-party crash reporting tools for their own symbol upload requirements. If you’re using Firebase Crashlytics or Sentry alongside Play Console’s native reporting, they each have separate symbol upload mechanisms and Gradle plugin configurations. Getting Play Console’s warning to clear doesn’t automatically mean Crashlytics or Sentry have what they need — those are configured independently.

Google Play Console

Prevention Tips

  • Add the debugSymbolLevel setting to your build.gradle once and it’ll apply to every future release build automatically — set it early in a project’s life rather than reactively after the first warning
  • Keep your Android Gradle Plugin reasonably current, since older versions require more manual symbol handling
  • If your app size is a concern, default to SYMBOL_TABLE rather than FULL unless you specifically need file and line-level debugging detail
  • Don’t chase this warning by trying to remove native dependencies — that’s solving the wrong problem and can break functionality your app actually needs

FAQ

Does this warning mean my app will be rejected from Play Store? No. It’s a recommendation, not a blocker — your app publishes fine either way, you just lose some crash-debugging detail if you skip it.

Will removing Flutter or React Native’s native code fix this permanently? That’s not really possible without abandoning the framework entirely, and it’s not necessary — the fix is packaging debug symbols properly, not eliminating native code.

Why did this warning suddenly appear on a project that never showed it before? Usually a new dependency pulled in native code, or an AGP/toolchain update changed default stripping behavior. Check what changed since your last clean release.

Is FULL always better than SYMBOL_TABLE? Not necessarily — FULL gives more detail but at a real file size cost. If you’re not doing deep native debugging, SYMBOL_TABLE is often the more practical choice.

Do I need to do this for every single release, or just once? Once it’s in your build.gradle, it applies automatically to every release build going forward — you don’t need to repeat the manual steps unless you’re doing a one-off manual zip upload on an older toolchain.

Editor’s Opinion

the funny thing about this warning is how scary it sounds for how boring the fix actually is. “contains native code” reads like something’s wrong when really its just flutter and rn doing what they always do. one line in build.gradle and your done, dont go tearing apart your dependencies trying to remove native code that isnt even a problem. wish more play console warnings were this easy honestly.

Written by ugur

Ugur is an editor and writer at (NSF Tech), specializing in technology and Windows. He produces in-depth, well-researched, and reliable stories with a strong focus on Windows, emerging technologies, digital culture, cybersecurity, AI developments, and innovative solutions shaping the future. His work aims to inform, inspire, and engage readers worldwide with accurate reporting and a clear editorial voice.

Contact: [email protected]