JetBrains/intellij-community · error · ConfigurationException
module.paths.validation.duplicate.source.root.error
module.paths.validation.duplicate.source.root.error
Error message
Module ''{0}''
must not contain source root ''{1}''.
The root already belongs to module ''{2}'' What it means
Thrown by ModulesConfigurator.throwDuplicateSourceRootError when a source root is claimed by a module whose content root is nested inside another module's content root that already owns that source root. The configurator determines the 'problematic' module (the one with the nested content root, via VfsUtilCore.isAncestor) and the 'correct' module, and rejects the model until the nested module stops claiming the source root.
Source
Thrown at java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java:339
/**
* Throws an appropriate error for duplicate source roots.
*/
private static void throwDuplicateSourceRootError(@NotNull VirtualFile srcRoot,
@NotNull VirtualFile contentRoot,
@NotNull VirtualFile anotherContentRoot,
@NotNull Map<VirtualFile, String> contentRootToModuleNameMap) throws ConfigurationException {
final String problematicModule;
final String correctModule;
if (VfsUtilCore.isAncestor(anotherContentRoot, contentRoot, true)) {
problematicModule = contentRootToModuleNameMap.get(anotherContentRoot);
correctModule = contentRootToModuleNameMap.get(contentRoot);
}
else {
problematicModule = contentRootToModuleNameMap.get(contentRoot);
correctModule = contentRootToModuleNameMap.get(anotherContentRoot);
}
throw new ConfigurationException(
JavaUiBundle.message("module.paths.validation.duplicate.source.root.error", problematicModule, srcRoot.getPresentableUrl(), correctModule)
);
}
/**
* Validates that source roots belong to the same module as their corresponding content root.
*/
private static void validateSourceRootsAcrossModules(@NotNull Map<VirtualFile, VirtualFile> srcRootsToContentRootMap,
@NotNull Map<VirtualFile, String> contentRootToModuleNameMap) throws ConfigurationException {
for (Map.Entry<VirtualFile, VirtualFile> entry : srcRootsToContentRootMap.entrySet()) {
final VirtualFile srcRoot = entry.getKey();
final VirtualFile correspondingContent = entry.getValue();
final String expectedModuleName = contentRootToModuleNameMap.get(correspondingContent);
for (VirtualFile candidateContent = srcRoot;
candidateContent != null && !candidateContent.equals(correspondingContent);
candidateContent = candidateContent.getParent()) {
final String moduleName = contentRootToModuleNameMap.get(candidateContent);View on GitHub (pinned to be881553f2)
Solutions
- Remove the source root from the 'problematic' module named in the message (Project Structure > Modules > that module > unmark/remove the folder)
- Or shrink the parent module's source roots so they no longer cover the child module's directory
- Re-import from the build tool (Gradle/Maven refresh) so content root ownership is derived correctly instead of hand-edited
Example fix
<!-- before: parent module owns p/src/main/java; child module also claims it --> <!-- parent.iml --> <content url="file://$PROJECT_DIR$/p"> <sourceFolder url="file://$PROJECT_DIR$/p/src/main/java"/> </content> <!-- child.iml --> <content url="file://$PROJECT_DIR$/p/src/main/java"> <sourceFolder url="file://$PROJECT_DIR$/p/src/main/java"/> </content> <!-- after: child keeps the dir as content root, parent stops marking it as source --> <!-- parent.iml --> <content url="file://$PROJECT_DIR$/p"/> <!-- child.iml --> <content url="file://$PROJECT_DIR$/p/src/main/java"> <sourceFolder url="file://$PROJECT_DIR$/p/src/main/java"/> </content>
Defensive patterns
Strategy: validation
Validate before calling
Map<VirtualFile, String> srcOwner = new HashMap<>();
for (Module m : modules) {
for (ContentEntry c : ModuleRootManager.getInstance(m).getContentEntries()) {
for (VirtualFile src : c.getSourceFolderFiles()) {
String prev = srcOwner.put(src, m.getName());
if (prev != null && !prev.equals(m.getName())) {
// nested overlap: unmark src from the nested module or shrink the parent's roots
}
}
}
} Try / catch
try {
configurator.apply();
} catch (ConfigurationException e) {
// message identifies problematic module and correct module; unmark the source root
// from the problematic module, then re-apply
} Prevention
- Avoid nested content roots: a submodule's content root must not sit inside a parent's marked source tree
- Re-import from Gradle/Maven after restructuring instead of hand-editing nested .iml roots
- When splitting modules, remove the parent's source-folder marks that cover child directories in the same commit
When it happens
Trigger: During apply-time validation, srcRootsToContentRootMap.put(srcRoot, contentRoot) finds the source root already mapped to a different content root; the classic shape is module A with content root 'p' + source root 'p/src/main/java', and module B with content root 'p/src/main/java' also claiming 'p/src/main/java' as a source root.
Common situations: Maven/Gradle import where a submodule directory sits inside the parent's source tree and both get content roots; hand-edited iml giving a submodule the parent's src as its own source root; importing nested builds (parent + child aggregator) twice with different roots.
Related errors
- module.paths.validation.duplicate.source.root.in.same.module.error
- module.paths.validation.duplicate.content.error
- Module '{0}' already exist in project. Please, specify anoth
- Module {name} has no content roots and will not be created.
- Enter module file location
AI-assisted analysis of JetBrains/intellij-community@be881553f2 (2026-08-14).
Data as JSON: /api/errors/28ad452364ee2fd7.
Report an issue: GitHub.