{"record":{"id":"39b6a9dbb8a8ada3","repo":"golang/go","slug":"git-remote-s-must-not-be-local-directory-use-u","errorCode":null,"errorMessage":"git remote (%s) must not be local directory (use URL syntax not host:path syntax)","messagePattern":"git remote \\((.+?)\\) must not be local directory \\(use URL syntax not host:path syntax\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/modfetch/codehost/git.go","lineNumber":69,"sourceCode":"\t\tif strings.Contains(remote, \"://\") { // Local flag, but URL provided\n\t\t\treturn nil, fmt.Errorf(\"git remote (%s) lookup disabled\", remote)\n\t\t}\n\t\tinfo, err := os.Stat(remote)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif !info.IsDir() {\n\t\t\treturn nil, fmt.Errorf(\"%s exists but is not a directory\", remote)\n\t\t}\n\t\tr.dir = remote\n\t\tr.mu.Path = r.dir + \".lock\"\n\t\tr.sha256Hashes = r.checkConfigSHA256(ctx)\n\t\treturn r, nil\n\t}\n\t// This is a remote path lookup.\n\tif !strings.Contains(remote, \"://\") { // No URL scheme, could be host:path\n\t\tif strings.Contains(remote, \":\") {\n\t\t\treturn nil, fmt.Errorf(\"git remote (%s) must not be local directory (use URL syntax not host:path syntax)\", remote)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"git remote (%s) must not be local directory\", remote)\n\t}\n\tvar err error\n\tr.dir, r.mu.Path, err = WorkDir(ctx, gitWorkDirType, r.remote)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tunlock, err := r.mu.Lock()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer unlock()\n\n\tif _, err := os.Stat(filepath.Join(r.dir, \"objects\")); err != nil {\n\t\trepoSha256Hash := false\n\t\tif refs, lrErr := r.loadRefs(ctx); lrErr == nil {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/modfetch/codehost/git.go#L51-L87","documentation":"Thrown by newGitRepo in remote mode (local=false) when the remote string contains no '://' scheme (so it's not a URL) but does contain ':' — matching the SCP-style 'host:path' syntax. Go's module system does not accept this syntax; it must use a full URL like ssh://host/path or git+ssh://.","triggerScenarios":"A module import or replace directive using SCP-style syntax like 'git@github.com:owner/repo.git' or 'host:path/to/repo' instead of a proper URL. This surfaces when go tries to resolve such a string as a git remote.","commonSituations":"Copy-pasting an SSH clone URL from GitHub/GitLab (which displays SCP-style) into a go.mod replace directive or an import path; using a private repo with SCP-style addressing.","solutions":["Convert SCP syntax to a full URL: 'git@github.com:owner/repo.git' becomes 'ssh://git@github.com/owner/repo.git'.","For replace directives, prefer filesystem paths for local development.","Set GOPRIVATE and use 'GOFLAGS=-insecure' only if needed for plain-http (not SCP) cases.","Use 'go env -w GOPRIVATE=github.com/owner/*' for private repos."],"exampleFix":"// before (go.mod)\nreplace example.com/mod => git@github.com:owner/repo.git\n// after\nreplace example.com/mod => ssh://git@github.com/owner/repo.git","handlingStrategy":"validation","validationCode":"func normalizeGitRemote(remote string) (string, error) {\n    if strings.Contains(remote, \"://\") {\n        return remote, nil // already a URL\n    }\n    // Detect SCP-style host:path\n    if idx := strings.Index(remote, \":\"); idx > 0 {\n        host := remote[:idx]\n        path := remote[idx+1:]\n        return \"ssh://\" + host + \"/\" + path, nil\n    }\n    return \"\", fmt.Errorf(\"%q has no URL scheme and is not SCP-style\", remote)\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Always use full URLs (ssh://, https://) in go.mod replace directives.","Convert SCP-style addresses before pasting into go.mod.","Set GOPRIVATE for private repos and use proper URL syntax."],"tags":["git","url","scp-syntax","ssh","replace-directive"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}