{"record":{"id":"5862eef2ad3628ad","repo":"golang/go","slug":"repository-rooted-at-s-cannot-contain-module-s","errorCode":null,"errorMessage":"repository rooted at %s cannot contain module %s","messagePattern":"repository rooted at (.+?) cannot contain module (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/modfetch/coderepo.go","lineNumber":126,"sourceCode":"\t//\tcodeRoot = gopkg.in/yaml.v2\n\t//\tpathPrefix = gopkg.in/yaml\n\t//\tpathMajor = .v2\n\t//\tpseudoMajor = v2\n\t//\n\t// Starting in 1.25, subdir may be passed in by the go-import meta tag.\n\t// So it may be the case that:\n\t//\tpath = github.com/rsc/foo/v2\n\t//\tcodeRoot = github.com/rsc/foo\n\t//\tsubdir = bar/subdir\n\t//\tpathPrefix = github.com/rsc/foo\n\t//\tpathMajor = /v2\n\t//\tpseudoMajor = v2\n\t// which means that codeDir = bar/subdir\n\n\tcodeDir := \"\"\n\tif codeRoot != path {\n\t\tif !hasPathPrefix(pathPrefix, codeRoot) {\n\t\t\treturn nil, fmt.Errorf(\"repository rooted at %s cannot contain module %s\", codeRoot, path)\n\t\t}\n\t\tcodeDir = strings.Trim(pathPrefix[len(codeRoot):], \"/\")\n\t}\n\tif subdir != \"\" {\n\t\tcodeDir = filepath.ToSlash(filepath.Join(codeDir, subdir))\n\t}\n\n\tr := &codeRepo{\n\t\tmodPath:     path,\n\t\tcode:        code,\n\t\tcodeRoot:    codeRoot,\n\t\tcodeDir:     codeDir,\n\t\tpathPrefix:  pathPrefix,\n\t\tpathMajor:   pathMajor,\n\t\tpseudoMajor: pseudoMajor,\n\t}\n\n\treturn r, nil","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/modfetch/coderepo.go#L108-L144","documentation":"newCodeRepo computes codeDir (subdirectory of the repo for the module root). When codeRoot != path it requires pathPrefix to start with codeRoot; otherwise the repository root cannot logically contain the module. The %s pair is codeRoot and the module path. Distinct from 977: here the path/codeRoot prefix check passed but pathPrefix (path minus version suffix) is not under codeRoot.","triggerScenarios":"path passes the initial hasPathPrefix(path, codeRoot) check, but after SplitPathVersion the resulting pathPrefix is not under codeRoot. Happens with malformed gopkg.in paths or when a meta tag's subdir interaction produces an inconsistent prefix.","commonSituations":"A vanity import where the path's version suffix splits the path in a way that leaves pathPrefix outside codeRoot; mixed major-version paths in one repo with an incorrect codeRoot; meta-tag subdir (Go 1.25+) misconfigured so the joined codeDir escapes the repo.","solutions":["Verify the module path, codeRoot, and (if present) subdir are mutually consistent — the path's non-version prefix must lie under codeRoot.","Correct the go-import meta tag so the repository root actually contains the module directory.","For multi-major repos, ensure each /vN path maps to a codeRoot that is a prefix of the path's prefix component.","Fall back to GOPROXY to fetch a pre-built zip and avoid the vanity resolution."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"func codeRootContainsPrefix(codeRoot, path string) bool {\n    prefix, _, ok := module.SplitPathVersion(path)\n    if !ok { return false }\n    return hasPathPrefix(prefix, codeRoot)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep module-to-repo-subdirectory mappings stable and documented.","For multi-major repos, ensure each /vN module's prefix lies within the advertised codeRoot.","Validate vanity meta tags with `GOPROXY=direct go list -m -versions <path>` before relying on them."],"tags":["module-path","vanity-import","subdir","major-version"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}