Repository Configuration in Gradle: Settings vs Project Repositories
Problem Statement
When trying to add JitPack or other Maven repositories to an Android or Gradle project, developers often encounter the error:
Caused by: org.gradle.api.InvalidUserCodeException: Build was configured to prefer settings repositories over project repositories but repository 'maven' was added by build file 'build.gradle'
This error occurs because newer versions of Gradle (6.8+) introduced a centralized repository declaration system that prioritizes settings-level repositories over project-level repositories.
Root Cause
Gradle 6.8 introduced central declaration of repositories, which provides better performance and consistency across multi-module projects. When your settings.gradle
file contains a dependencyResolutionManagement
block, Gradle expects all repository declarations to be centralized there rather than in individual build.gradle
files.
Solutions
Option 1: Centralized Repository Configuration (Recommended)
The modern approach is to declare all repositories in your settings.gradle
file:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
Full settings.gradle example
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
// Add other repositories here
}
}
rootProject.name = "YourAppName"
include ':app'
Option 2: Adjust Repository Resolution Mode
If you need to maintain some repository declarations in your build files, change the repositories mode:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
This mode allows project-level repositories but gives preference to settings-level declarations.
Option 3: Remove Centralized Configuration (Legacy Approach)
If you prefer the traditional approach, remove the dependencyResolutionManagement
block from settings.gradle
entirely and use project-level repository declarations:
// In your root build.gradle
allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
WARNING
This approach is not recommended for new projects as the centralized repository management offers better performance and consistency.
Handling Authenticated Repositories
For repositories requiring authentication (like GitHub Packages), use this pattern:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/OWNER/REPOSITORY")
credentials {
username = project.findProperty("githubUsername") ?: ""
password = project.findProperty("githubToken") ?: ""
}
}
}
}
Best Practices
- Use centralized repository declarations for better performance and maintainability
- Keep repository list minimal to reduce dependency resolution time
- Use credentials properties for authenticated repositories rather than hardcoding secrets
- Remove deprecated repositories like jcenter() which is being sunset
Common Issues and Fixes
- Sync fails after changes: Click "Sync Now" in Android Studio or run
./gradlew --refresh-dependencies
- Duplicate repository errors: Ensure you're not declaring the same repository in both settings.gradle and build.gradle
- Authentication issues: Verify credentials and network access for private repositories
By following these patterns, you can efficiently manage dependencies while avoiding the "prefer settings repositories" error that occurs when mixing old and new repository declaration approaches.