{"record":{"id":"78ed22f633e5e7f0","repo":"golang/go","slug":"s-s-used-for-two-different-module-paths-s-and","errorCode":null,"errorMessage":"%s@%s used for two different module paths (%s and %s)","messagePattern":"(.+?)@(.+?) used for two different module paths \\((.+?) and (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/modload/load.go","lineNumber":2044,"sourceCode":"\t\t\t// directives, both fixed for the lifetime of mg, so skip it on\n\t\t\t// subsequent calls sharing the same graph.\n\t\t\tmg.checkPathsOnce.Do(func() {\n\t\t\t\tcheckMultiplePathsUncached(ld, pld, mg.BuildList())\n\t\t\t})\n\t\t\treturn\n\t\t}\n\t}\n\tcheckMultiplePathsUncached(ld, pld, pld.requirements.rootModules)\n}\n\nfunc checkMultiplePathsUncached(ld *Loader, pld *packageLoader, mods []module.Version) {\n\tfirstPath := map[module.Version]string{}\n\tfor _, mod := range mods {\n\t\tsrc := resolveReplacement(ld, mod)\n\t\tif prev, ok := firstPath[src]; !ok {\n\t\t\tfirstPath[src] = mod.Path\n\t\t} else if prev != mod.Path {\n\t\t\tpld.error(fmt.Errorf(\"%s@%s used for two different module paths (%s and %s)\", src.Path, src.Version, prev, mod.Path))\n\t\t}\n\t}\n}\n\n// checkTidyCompatibility emits an error if any package would be loaded from a\n// different module under rs than under ld.requirements.\nfunc (pld *packageLoader) checkTidyCompatibility(ld *Loader, ctx context.Context, rs *Requirements, compatVersion string) {\n\tgoVersion := rs.GoVersion(ld)\n\tsuggestUpgrade := false\n\tsuggestEFlag := false\n\tsuggestFixes := func() {\n\t\tif pld.AllowErrors {\n\t\t\t// The user is explicitly ignoring these errors, so don't bother them with\n\t\t\t// other options.\n\t\t\treturn\n\t\t}\n\n\t\t// We print directly to os.Stderr because this information is advice about","sourceCodeStart":2026,"sourceCodeEnd":2062,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/modload/load.go#L2026-L2062","documentation":"Thrown by checkMultiplePathsUncached (load.go:2044) when the same module source (resolveReplacement(mod) — which resolves to the module itself or its replacement) is referenced by two different module paths. The map firstPath[src] tracks the first path seen for each source; if a later module shares the source but has a different Path, the conflict is reported. This indicates a module graph where one physical source is ambiguously attributed to two logical modules.","triggerScenarios":"Two different module paths in the build list resolve (possibly via 'replace' directives) to the same filesystem source or the same module@version. For example, replace directives pointing distinct module paths at the same local directory, or a replacement that aliases module paths.","commonSituations":"Multiple 'replace' directives in go.mod pointing different module paths at the same local directory. A forked module published under a new path but accidentally sharing a version string with the original. Complex workspace setups with overlapping replacements.","solutions":["Inspect go.mod and go.work 'replace' directives for two different module paths pointing at the same source.","Ensure each module path maps to a distinct source directory or version.","If using a local replacement, give each replaced module its own directory."],"exampleFix":"// before (go.mod)\nreplace (\n    example.com/a => ./local\n    example.com/b => ./local\n)\n\n// after — distinct sources per module path\nreplace (\n    example.com/a => ./local-a\n    example.com/b => ./local-b\n)","handlingStrategy":"validation","validationCode":"// Detect replace directives that alias distinct module paths to the same source.\nfunc checkDuplicateReplaces(replacements []Replace) error {\n    seen := map[string]string{} // source -> first path\n    for _, r := range replacements {\n        src := r.New.Path + \"@\" + r.New.Version\n        if r.New.Version == \"\" {\n            src = r.New.Path // local replacement\n        }\n        if prev, ok := seen[src]; ok && prev != r.Old.Path {\n            return fmt.Errorf(\"%s used for two module paths (%s and %s)\", src, prev, r.Old.Path)\n        }\n        seen[src] = r.Old.Path\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure each 'replace' directive targets a distinct source directory or version.","Avoid pointing multiple module paths at the same local directory in replace directives.","Review 'go mod edit -print' for overlapping replacements before committing."],"tags":["replace-directive","module-graph","go-mod","ambiguity"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}