apache/maven · warning
Duplicate enabled source detected: lang=%s, scope=%s, module
Error message
Duplicate enabled source detected: lang=%s, scope=%s, module=%s, directory=%s. First enabled source wins, this duplicate is ignored.
What it means
While materializing Maven 4 <source> declarations into SourceRoot entries, SourceHandlingContext.shouldAddSource() detected two enabled sources with identical identity: same language, same project scope, same module, and the same normalized directory path. The first declaration wins and the duplicate is dropped; a WARNING ModelProblem is also added to the problem collector, so the message reappears in the 'problems encountered while building the effective model' summary. Only enabled sources participate; disabled ones never collide. Introduced with the unified source handling in Maven 4.0.0.
Source
Thrown at impl/maven-core/src/main/java/org/apache/maven/project/SourceHandlingContext.java:131
"Adding disabled source (will be filtered by getEnabledSourceRoots): lang={}, scope={}, module={}, dir={}",
sourceRoot.language(),
sourceRoot.scope(),
sourceRoot.module().orElse(null),
sourceRoot.directory());
return true;
}
// Normalize path for consistent duplicate detection (handles symlinks, relative paths)
Path normalizedDir = sourceRoot.directory().toAbsolutePath().normalize();
SourceKey key = new SourceKey(
sourceRoot.language(), sourceRoot.scope(), sourceRoot.module().orElse(null), normalizedDir);
if (!declaredSources.add(key)) {
String message = String.format(
"Duplicate enabled source detected: lang=%s, scope=%s, module=%s, directory=%s. "
+ "First enabled source wins, this duplicate is ignored.",
key.language(), key.scope(), key.module() != null ? key.module() : "(none)", key.directory());
LOGGER.warn(message);
result.getProblemCollector()
.reportProblem(new DefaultModelProblem(
message,
Severity.WARNING,
Version.V41,
project.getModel().getDelegate(),
-1,
-1,
null));
return false; // Don't add duplicate enabled source
}
LOGGER.debug(
"Adding and tracking enabled source: lang={}, scope={}, module={}, dir={}",
key.language(),
key.scope(),
key.module(),
key.directory());View on GitHub (pinned to e4093d4e12)
Solutions
- Run mvn help:effective-pom and search for repeated <source> blocks with the same <directory> under the same build scope
- Delete one of the duplicate <source> declarations, keeping the intended one
- If both are conditionally needed, mark the less important one with <enabled>false</enabled> so it never competes
- Remove legacy build-helper / add-test-source mojos that add a directory Maven 4 already tracks via <source>
Example fix
<!-- before: same directory declared twice for lang=java, scope=main -->
<build>
<sources>
<source>
<directory>src/main/java</directory>
<language>java</language>
</source>
<source>
<directory>src/main/java</directory>
<language>java</language>
<module>com.example.app</module>
</source>
</sources>
</build>
<!-- after: single declaration; extra roots get their own directory -->
<build>
<sources>
<source>
<directory>src/main/java</directory>
<language>java</language>
</source>
<source>
<directory>src/generated/java</directory>
<language>java</language>
</source>
</sources>
</build> Defensive patterns
Strategy: validation
Validate before calling
# Lint POMs for duplicate source identities before building (bash)
python3 - <<'EOF'
import xml.etree.ElementTree as ET, sys
ns = {'m': 'http://maven.apache.org/POM/4.0.0'}
for pom in sys.argv[1:]:
root = ET.parse(pom).getroot()
seen = set()
for s in root.iter('{http://maven.apache.org/POM/4.0.0}source'):
if s.findtext('m:enabled', 'true', ns) in ('true', 'True'):
key = (s.findtext('m:language', ns), s.findtext('m:directory', ns))
if key in seen: sys.exit(f"duplicate enabled source {key} in {pom}")
seen.add(key)
EOF Prevention
- Declare each source directory exactly once per language/scope combination in the POM
- Remove legacy build-helper add-source goals that duplicate directories Maven 4 tracks natively
- When merging sources from profiles, verify with mvn help:effective-pom that no directory repeats
When it happens
Trigger: A POM (or an effective model merged from profiles/parents) declares two <source> elements under <build> with the same language/scope/module and directory, both enabled (default). Typical: an explicit <source> duplicating the conventional src/main/java declared via a default profile plus one in the base build section.
Common situations: Upgrading a project to Maven 4 <source> declarations and keeping the legacy build-helper add-source or build-helper-maven-plugin addition of the same directory; a profile that adds a source root also present in the active base model; copy-pasted <source> blocks with identical directories.
Related errors
- lifecycle bindings injector is missing
- neither pomFile nor modelSource can be null
- request.workspaceModelResolver and request.modelResolver can
- Unable to build project
- Error evaluating plugin parameter expression: ${expression}
AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21).
Data as JSON: /api/errors/cae119f25d255bf8.
Report an issue: GitHub.