Skip to main content

Flutter Build Failed: Namespace Not Specified in Android Gradle Plugin 8.0+

 You successfully upgraded your Flutter project's dependencies, bumped the Android Gradle Plugin (AGP) version to 8.0+ to keep up with the Play Store requirements, and hit run. Instead of the application launching, the build terminates immediately with the following error:

Target debug_android_application failed: Exception: Gradle task assembleDebug failed with exit code 1

* What went wrong:
Execution failed for task ':app:processDebugMainManifest'.
> com.android.builder.errors.EvalIssueException: Namespace not specified. Please specify a namespace in the module's build.gradle file like so:

  android {
      namespace 'com.example.my_app'
  }

This is not a transient cache issue; flutter clean will not save you here. This is a breaking change enforced by AGP 8.0 regarding how Android resource compilation handles package names.

The Root Cause: Decoupling Identity from Compilation

Historically, the package attribute in AndroidManifest.xml served two distinct purposes:

  1. Application ID: The unique identifier for your app on the Play Store (e.g., com.company.app).
  2. R Class Namespace: The Java/Kotlin package under which the R class (resource references) and BuildConfig class were generated.

As build systems matured, this dual responsibility became a bottleneck. The build system had to parse the XML manifest just to determine where to generate code, slowing down configuration phases.

Starting with AGP 7.x, Google deprecated this behavior. With AGP 8.0, it is now removed. The build system demands that the compilation namespace be declared explicitly in the build scripts (Gradle), completely separating it from the application ID or manifest configuration.

The Solution

To resolve this, you must migrate the namespace declaration from the manifest to the module-level build.gradle file.

Step 1: Update the App-Level build.gradle

Open your Flutter project's Android module configuration. Path: android/app/build.gradle

Locate the android block. You must inject the namespace property. This usually matches your original package name.

android {
    // 1. ADD THIS LINE
    // This defines where R.java and BuildConfig.java are generated.
    namespace "com.example.your_project_name"

    // Existing configuration
    compileSdkVersion flutter.compileSdkVersion
    ndkVersion flutter.ndkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }

    kotlinOptions {
        jvmTarget = '17'
    }

    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }

    defaultConfig {
        // 2. VERIFY THIS
        // This remains the Play Store / Device Install ID.
        // It can be different from the namespace, but in Flutter apps, 
        // they are usually identical.
        applicationId "com.example.your_project_name"
        
        minSdkVersion flutter.minSdkVersion
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

Step 2: Clean the Android Manifest

Once the namespace is defined in Gradle, the package attribute in your manifest becomes redundant (and potentially conflicting if they differ).

Path: android/app/src/main/AndroidManifest.xml

Before:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.your_project_name">
    <!-- ... -->
</manifest>

After (Correct):

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- The 'package' attribute is removed. 
         Gradle now handles the namespace. -->
    <application
        android:label="your_project_name"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <!-- ... -->
    </application>
</manifest>

Step 3: Handle Legacy Flutter Plugins (Advanced)

If the build fails inside a third-party Flutter plugin (e.g., :some_old_plugin:processDebugMainManifest), it means the plugin author has not updated their library to support AGP 8.0.

While the ideal fix is upgrading the plugin version in pubspec.yaml, you may be stuck with an unmaintained package. You can temporarily force a namespace injection via your root android/build.gradle.

Path: android/build.gradle (Root Level)

subprojects {
    afterEvaluate { project ->
        if (project.hasProperty('android')) {
            project.android {
                // Check if namespace is missing and manifest file exists
                if (namespace == null && file("src/main/AndroidManifest.xml").exists()) {
                    def manifestFile = file("src/main/AndroidManifest.xml")
                    def manifestParser = new XmlSlurper().parse(manifestFile)
                    def packageAttr = manifestParser.@package.text()
                    
                    if (packageAttr != null && !packageAttr.isEmpty()) {
                        println "Auto-injecting namespace '${packageAttr}' for project ${project.name}"
                        namespace = packageAttr
                    }
                }
            }
        }
    }
}

Note: Use this script only as a stop-gap measure. The sustainable solution is for plugin maintainers to update their build configuration.

Technical Explanation

When Gradle syncs your project using AGP 8.0+:

  1. Configuration Phase: Gradle reads the build.gradle file. It looks for the namespace property to establish the Java package structure for generated classes.
  2. Execution Phase: If namespace is missing, the task processDebugMainManifest throws the EvalIssueException because it is no longer permitted to scan AndroidManifest.xml to infer this data.

By explicitly setting the namespace in the DSL (Domain Specific Language), you decouple resource generation from artifact packaging. This allows you, for example, to have an internal namespace of com.internal.code for your Java classes while publishing the app to the store as com.public.product.

Conclusion

The shift to AGP 8.0 represents a stricter enforcement of build artifacts. While manual migration of build.gradle files is tedious, it results in a more deterministic and performant build graph. For DevOps teams maintaining CI/CD pipelines, ensure your Docker images include the correct JDK (usually JDK 17 for AGP 8.0) and that all internal modules explicitly declare their namespaces.