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.
// 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
Recommended solution
Enable buildConfig per module
Best Practice (AGP 8.0+): Explicitly enable BuildConfig generation in each module's build.gradle.kts
(or build.gradle
):
android {
buildFeatures {
buildConfig = true // Enables BuildConfig generation
}
}
Full implementation example
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:
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:
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:
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:
# 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:
- Open your project in Android Studio
- Right-click your project's root directory
- Select Refactor > Migrate Build Config to Gradle Build Files
- 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:
- Reduced build overhead: Disabling BuildConfig by default speeds up builds for modules not needing runtime constants
- Explicit configuration: Requires conscious declaration of build features
- 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:
- Run a build (
./gradlew assembleDebug
) - Check generated files in:
app/build/generated/source/buildConfig/debug/com/yourpackage/BuildConfig.java
- Verify your custom fields appear in the generated file
Final configuration
Adopt this pattern in every module using BuildConfig:
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"))
}
}
}
android {
buildFeatures {
buildConfig true // Groovy syntax
}
androidComponents {
onVariants { variant ->
variant.buildConfigFields.put('FIELD_NAME',
new BuildConfigField('Type', 'Value', 'Description'))
}
}
}