Skip to content

Fix Build Type contains custom BuildConfig fields error

Problem statement

When using newer versions of Android Studio (Flamingo or later) with Kotlin 1.8.0+ and Android Gradle Plugin (AGP) 8.0+alpha09, you might encounter this error during builds:

Build Type 'release' contains custom BuildConfig fields, but the feature is disabled.

This error occurs when your Gradle configuration includes custom BuildConfig fields (like API keys or timestamps), but AGP's buildConfig generation feature is disabled. Starting with AGP 8.0, BuildConfig generation is disabled by default, making previously working configurations fail in newer environments.

gradle
// This custom field triggers the error if buildConfig is disabled
buildConfigField("String", "API_KEY", "\"YOUR_API_KEY\"")

The core problem stems from:

  • AGP 8.0+ deprecating automatic BuildConfig generation
  • Existing buildConfigField declarations becoming invalid without explicit opt-in
  • Legacy global options (gradle.properties settings) now causing conflicts

Enable buildConfig per module

Best Practice (AGP 8.0+): Explicitly enable BuildConfig generation in each module's build.gradle.kts (or build.gradle):

kotlin
android {
    buildFeatures {
        buildConfig = true  // Enables BuildConfig generation
    }
}

Full implementation example

kotlin
plugins {
    id("com.android.application")
    // other plugins...
}

android {
    buildFeatures {
        buildConfig = true  // Critical for custom BuildConfig fields
    }

    buildTypes {
        getByName("release") {
            // Your release configuration
            buildConfigField("String", "API_ENDPOINT", "\"https://prod.api.com\"")
        }
        getByName("debug") {
            buildConfigField("String", "API_ENDPOINT", "\"https://dev.api.com\"")
        }
    }
}

Alternative for multi-module projects

If you need to apply this to all modules:

kotlin
subprojects {
    afterEvaluate {
        extensions.findByType<com.android.build.gradle.BaseExtension>()?.apply {
            buildFeatures {
                if (buildConfig != true) {
                    buildConfig = true
                }
            }
        }
    }
}

Adding custom BuildConfig fields (modern method)

When enabled, add custom fields with the modern androidComponents API:

kotlin
import com.android.build.api.variant.BuildConfigField

androidComponents {
    onVariants { variant ->
        // Add BUILD_TIME timestamp
        variant.buildConfigFields.put(
            "BUILD_TIME", 
            BuildConfigField("Long", System.currentTimeMillis().toString(), "Build timestamp")
        )
        
        // Add environment-specific API key
        val apiKey = when(variant.name) {
            "release" -> "PROD_KEY"
            else -> "DEV_KEY"
        }
        variant.buildConfigFields.put(
            "API_KEY", 
            BuildConfigField("String", "\"$apiKey\"", "API access key")
        )
    }
}

Access fields in code like traditional BuildConfig values:

kotlin
val apiUrl = BuildConfig.API_ENDPOINT
val buildTime = Instant.ofEpochMilli(BuildConfig.BUILD_TIME)

Deprecated approach to avoid

DO NOT USE (Deprecated in AGP 8.0)

Adding this to gradle.properties is deprecated and will be removed in AGP 9.0:

ini
# DEPRECATED - Causes future compatibility issues
android.defaults.buildfeatures.buildconfig=true

If you have this line, remove it immediately and migrate to the per-module solution above.

Automated migration (Android Studio Jellyfish+)

For Android Studio Jellyfish (2023.3.1+) or newer:

  1. Open your project in Android Studio
  2. Right-click your project's root directory
  3. Select Refactor > Migrate Build Config to Gradle Build Files
  4. Follow the IDE prompts to automatically convert custom fields

TIP

This automated refactor handles:

  • Removal of deprecated gradle.properties flags
  • Conversion of legacy buildConfigField declarations
  • Proper placement of android.buildFeatures.buildConfig flags

Explanation of changes

The AGP changes reflect several development shifts:

  1. Reduced build overhead: Disabling BuildConfig by default speeds up builds for modules not needing runtime constants
  2. Explicit configuration: Requires conscious declaration of build features
  3. Modern API adoption: The androidComponents API allows safer type handling and variant-specific values

Legacy solutions that modify gradle.properties are:

  • Deprecated in AGP 8.0
  • Scheduled for removal in AGP 9.0
  • Potential causes of hidden dependency conflicts

Using the recommended method ensures compatibility with future AGP updates while keeping your configuration modular and transparent.

Verification

To confirm BuildConfig is enabled and working:

  1. Run a build (./gradlew assembleDebug)
  2. Check generated files in:
    app/build/generated/source/buildConfig/debug/com/yourpackage/BuildConfig.java
  3. Verify your custom fields appear in the generated file

Generated BuildConfig.java screenshot

Final configuration

Adopt this pattern in every module using BuildConfig:

kotlin
android {
    // Required to use custom BuildConfig fields
    buildFeatures {
        buildConfig = true
    }
    
    // Optional modern field declaration
    androidComponents {
        onVariants { variant ->
            variant.buildConfigFields.put("FIELD_NAME", 
                BuildConfigField("Type", "Value", "Description"))
        }
    }
}
groovy
android {
    buildFeatures {
        buildConfig true  // Groovy syntax
    }
    
    androidComponents {
        onVariants { variant ->
            variant.buildConfigFields.put('FIELD_NAME', 
                new BuildConfigField('Type', 'Value', 'Description'))
        }
    }
}