{"record":{"id":"c15e2362e682d8be","repo":"hashicorp/terraform","slug":"github-urls-should-be-github-com-username-repo","errorCode":null,"errorMessage":"GitHub URLs should be github.com/username/repo","messagePattern":"GitHub URLs should be github\\.com/username/repo","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/getmodules/moduleaddrs/detect_git.go","lineNumber":47,"sourceCode":"\t\treturn \"\", false, nil\n\t}\n\n\treturn \"git::\" + u.String(), true, nil\n}\n\n// detectGitHub detects shorthand schemeless references to github.com and\n// translates them into git HTTP source addresses.\nfunc detectGitHub(src string) (string, bool, error) {\n\tif len(src) == 0 {\n\t\treturn \"\", false, nil\n\t}\n\n\tif strings.HasPrefix(src, \"github.com/\") {\n\t\tsrc, rawQuery, _ := strings.Cut(src, \"?\")\n\n\t\tparts := strings.Split(src, \"/\")\n\t\tif len(parts) < 3 {\n\t\t\treturn \"\", false, fmt.Errorf(\n\t\t\t\t\"GitHub URLs should be github.com/username/repo\")\n\t\t}\n\n\t\turlStr := fmt.Sprintf(\"https://%s\", strings.Join(parts[:3], \"/\"))\n\t\turl, err := url.Parse(urlStr)\n\t\tif err != nil {\n\t\t\treturn \"\", true, fmt.Errorf(\"error parsing GitHub URL: %s\", err)\n\t\t}\n\t\turl.RawQuery = rawQuery\n\n\t\tif !strings.HasSuffix(url.Path, \".git\") {\n\t\t\turl.Path += \".git\"\n\t\t}\n\n\t\tif len(parts) > 3 {\n\t\t\turl.Path += \"//\" + strings.Join(parts[3:], \"/\")\n\t\t}\n","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/getmodules/moduleaddrs/detect_git.go#L29-L65","documentation":"Returned by detectGitHub (detect_git.go:47) when a source string starts with 'github.com/' but has fewer than 3 path segments after splitting on '/'. The shorthand expects github.com/<username>/<repo> at minimum, so anything shorter (e.g. just 'github.com/' or 'github.com/username') is rejected as structurally incomplete.","triggerScenarios":"A module source using the github.com shorthand but missing the repository segment. detectGitHub splits on '/', requires len(parts) >= 3, and otherwise returns this error. The source has already been confirmed to start with 'github.com/'.","commonSituations":"Writing source = \"github.com/hashicorp\" (missing repo) or source = \"github.com/\" (missing both). Truncated copy-paste of a GitHub URL. Forgetting the repo name when migrating from a local path.","solutions":["Provide the full shorthand: github.com/<username>/<repo>, e.g. github.com/hashicorp/example.","Optionally append a subdirectory path or query (e.g. ?ref=v1.2.0) after the repo.","If you need a specific commit/branch, add ?ref=<git-ref>.","Verify the URL with a browser before pasting it into source."],"exampleFix":"# before\nsource = \"github.com/hashicorp\"\n\n# after — include username AND repo\nsource = \"github.com/hashicorp/example\"\n# optionally:\n# source = \"github.com/hashicorp/example//modules/vpc?ref=v1.0.0\"","handlingStrategy":"validation","validationCode":"// Validate a github.com shorthand has at least user/repo\nfunc validGitHubShorthand(src string) bool {\n    if !strings.HasPrefix(src, \"github.com/\") {\n        return true\n    }\n    base := strings.SplitN(src, \"?\", 2)[0]\n    return len(strings.Split(base, \"/\")) >= 3\n}","typeGuard":"func isCompleteGitHubShorthand(src string) bool {\n    if !strings.HasPrefix(src, \"github.com/\") {\n        return false\n    }\n    base := strings.SplitN(src, \"?\", 2)[0]\n    return len(strings.Split(base, \"/\")) >= 3\n}","tryCatchPattern":null,"preventionTips":["Always include both username and repo in github.com shorthand.","Verify the URL resolves in a browser before pasting into source.","Use ?ref=<git-ref> for version pinning after the repo segment."],"tags":["getmodules","github","module-source","url-parsing","modules"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}