{"record":{"id":"b63b28a0f3054dd6","repo":"JetBrains/intellij-community","slug":"module-paths-validation-duplicate-source-root-in-s","errorCode":"module.paths.validation.duplicate.source.root.in.same.module.error","errorMessage":"Source root ''{0}'' is duplicated in module ''{1}''.","messagePattern":"Source root ''(.+?)'' is duplicated in module ''(.+?)''\\.","errorType":"validation","errorClass":"ConfigurationException","httpStatus":null,"severity":"error","filePath":"java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java","lineNumber":290,"sourceCode":"    @NotNull Map<VirtualFile, VirtualFile> srcRootsToContentRootMap\n  ) throws ConfigurationException {\n\n    // TODO IDEA-376062 allow duplicates only for supported build systems\n    boolean duplicatesAreAllowed = CodeInsightContexts.isSharedSourceSupportEnabled(myProject);\n    if (duplicatesAreAllowed) {\n      return;\n    }\n\n    final ModuleRootModel rootModel = moduleEditor.getRootModel();\n    final ContentEntry[] contents = rootModel.getContentEntries();\n    final String moduleName = moduleEditor.getName();\n\n    // Check for duplicate source roots within the same module\n    Set<VirtualFile> sourceRoots = new HashSet<>();\n    for (ContentEntry content : contents) {\n      for (VirtualFile root : content.getSourceFolderFiles()) {\n        if (!sourceRoots.add(root)) {\n          throw new ConfigurationException(\n            JavaUiBundle.message(\"module.paths.validation.duplicate.source.root.in.same.module.error\", root.getPresentableUrl(),\n                                 moduleName));\n        }\n      }\n    }\n\n    // Check for duplicate content roots across modules and map source roots to content roots\n    for (ContentEntry contentEntry : contents) {\n      final VirtualFile contentRoot = contentEntry.getFile();\n      if (contentRoot == null) {\n        continue;\n      }\n\n      // Check for duplicate content roots\n      final String previousName = contentRootToModuleNameMap.put(contentRoot, moduleName);\n      if (previousName != null && !previousName.equals(moduleName)) {\n        throw new ConfigurationException(\n          JavaUiBundle.message(\"module.paths.validation.duplicate.content.error\", contentRoot.getPresentableUrl(), previousName, moduleName)","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/JetBrains/intellij-community/blob/be881553f2a76ac8b4ea53950d93f0de78295c19/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java#L272-L308","documentation":"Thrown by ModulesConfigurator during Project Structure apply-time validation when the same source root VirtualFile appears twice within a single module's content entries. Duplicate source roots make indexing and compilation ambiguous, so the configurator rejects the whole module model update.","triggerScenarios":"Calling the configurator's validation (moduleEditor.getRootModel() content entries) after the user added the same folder as a source root under two different content entries of one module — the Set<VirtualFile> add() returns false on the second occurrence.","commonSituations":"Marking 'src' as Sources under two content roots that overlap; editing a misconfigured .iml by hand that lists the same source URL twice; copy-pasting a content entry in the iml; module with both 'src' and 'src/main/java' where the parent got marked too (exact duplicate case).","solutions":["In Project Structure > Modules, expand the content entries and unmark/remove the duplicated source root so each folder appears once","Edit the .iml directly: find the repeated <sourceFolder url=\"...\"> entries and delete the duplicates, then reload","If two content entries overlap, remove one of the overlapping content entries entirely"],"exampleFix":"<!-- before: my-module.iml -->\n<component name=\"NewModuleRootManager\">\n  <content url=\"file://$MODULE_DIR$/a\">\n    <sourceFolder url=\"file://$MODULE_DIR$/a/src\" isTestSource=\"false\"/>\n  </content>\n  <content url=\"file://$MODULE_DIR$/b\">\n    <sourceFolder url=\"file://$MODULE_DIR$/a/src\" isTestSource=\"false\"/> <!-- duplicate -->\n  </content>\n</component>\n\n<!-- after -->\n<component name=\"NewModuleRootManager\">\n  <content url=\"file://$MODULE_DIR$/a\">\n    <sourceFolder url=\"file://$MODULE_DIR$/a/src\" isTestSource=\"false\"/>\n  </content>\n  <content url=\"file://$MODULE_DIR$/b\"/>\n</component>","handlingStrategy":"validation","validationCode":"Set<VirtualFile> seen = new HashSet<>();\nfor (ContentEntry c : rootModel.getContentEntries()) {\n  for (VirtualFile root : c.getSourceFolderFiles()) {\n    if (!seen.add(root)) {\n      // remove the duplicate source folder via ContentEntry.removeSourceFolder before apply\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  modulesConfigurator.apply(); // or commit module editor\n} catch (ConfigurationException e) {\n  // parse module name / root from message, unmark the duplicate, then let user re-apply\n}","preventionTips":["Do not hand-duplicate <sourceFolder> entries in .iml files","When marking folders as Sources, check the folder is not already marked under another content entry","Let Gradle/Maven import own the module layout instead of editing roots manually"],"tags":["module","source-root","duplicate","project-structure","iml","intellij"],"backgroundTag":null,"analyzedSha":"be881553f2a76ac8b4ea53950d93f0de78295c19","analyzedAt":"2026-08-14T14:13:06.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}