Fix “compile against version 36 or later”: Flutter's compileSdk Error, Explained
If your Flutter Android build just died on :app:checkDebugAarMetadata (or its checkReleaseAarMetadata twin) with a message like “Dependency 'androidx.core:core:x.y.z' requires libraries and applications that depend on it to compile against version 36 or later of the Android APIs” — the fix is one line: raise compileSdk to 36 in android/app/build.gradle. It will not drop older devices — that is minSdk's job, not compileSdk's. The rest of this page explains why the error appears out of nowhere, and the two situations where the one-liner is not enough.
What the AAR metadata check actually verifies
Every Android library (an .aar) carries metadata declaring the minimum API level it was compiled against. The Android Gradle Plugin's checkAarMetadata tasks read those declarations for every dependency in the graph and compare them with your module's compileSdk. If any dependency demands a higher level than yours, the build stops before compilation even starts. It is a contract check, not a compiler error — which is why the message names the dependency, not a line of your code.
The important nuance: compileSdk is about the API surface visible at compile time. Raising it does not change your minSdk (which devices can install) or your targetSdk (which behavior era Android applies at runtime). Treating those three as one number is the single most common reason people fear this fix.
Why it broke this week and not last week
Your code did not change — your dependency graph did. As androidx libraries and Flutter plugins ship releases compiled against API 36, their AAR requirements rise with them, and the first build that resolves a new release trips the check. You can watch the wave roll through plugin issue trackers in real time: file_picker and syncfusion_flutter_pdfviewer, among many others, both carry open “adapt to API 36” issues. A pinned pubspec.lock postpones the moment; any pub upgrade, fresh checkout, or CI cache miss brings it forward again.
The one-line fix
In android/app/build.gradle (or .gradle.kts), inside the android {} block:
android {
compileSdk = 36
// minSdk and targetSdk stay as they are
}Many Flutter templates write compileSdk = flutter.compileSdkVersion, inheriting whatever your installed Flutter SDK defaults to. That indirection is fine — until a plugin runs ahead of your Flutter version's default. If the error persists after “raising” it, check you replaced the indirection with the explicit number rather than editing a value that gets overridden.
The messy case: a plugin module pins its own compileSdk
Here is the shape that eats an afternoon. Your app module says 36, but the failing module is a plugin — the error path reads :some_plugin:checkDebugAarMetadata instead of :app:. Plugin modules carry their own build scripts, and some pin an older compileSdk that your app-level setting does not touch. We hit exactly this combination on a real customer project in July: one plugin's new release demanded 36 while another plugin in the same app pinned 34 — individually reasonable, jointly unbuildable.
The clean fix without forking anyone's plugin is a subprojects override in the root build script, applied at configuration time, that raises any Android module below the floor:
// android/build.gradle (project root)
subprojects {
afterEvaluate {
if (project.hasProperty("android")) {
def androidExt = project.android
if (androidExt.compileSdk != null && androidExt.compileSdk < 36) {
androidExt.compileSdk = 36
}
}
}
}(Kotlin-DSL projects need the reflective equivalent; the idea is identical.) This is also precisely what our pipeline injects automatically when the metadata check trips — the repair raises every module to the required floor, the image already ships the API 36 platform and build tools, and the build re-runs without you editing anything.
If you'd rather not maintain the toolchain at all
This error class is exactly why we built the source pipeline the way we did. Upload your Flutter project and the build runs on an image with current SDK, JDK and build tools; the classifier recognizes the AAR-metadata wording, extracts which dependency demanded what, and applies the compileSdk floor across app and plugin modules before retrying. The same repair family covers the missing Gradle wrapper, AGP and Kotlin versions below the toolchain floor, and core-library desugaring — the walls that stack up when a project sits untouched for six months. First build is free, and a failed build refunds its credit with the real cause named, not “exit code 1”. For the broader picture of building Flutter APKs without a local Android setup, start with our Flutter APK online build guide — or the old-Flutter-project guide if your app predates null safety.
Code2Native Engineering
Engineering team
Written by the Code2Native engineering team — the people who build and operate the cloud build pipeline.