golang/go · error
git remote (%s) must not be local directory (use URL syntax
Error message
git remote (%s) must not be local directory (use URL syntax not host:path syntax)
What it means
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://.
Source
Thrown at src/cmd/go/internal/modfetch/codehost/git.go:69
if strings.Contains(remote, "://") { // Local flag, but URL provided
return nil, fmt.Errorf("git remote (%s) lookup disabled", remote)
}
info, err := os.Stat(remote)
if err != nil {
return nil, err
}
if !info.IsDir() {
return nil, fmt.Errorf("%s exists but is not a directory", remote)
}
r.dir = remote
r.mu.Path = r.dir + ".lock"
r.sha256Hashes = r.checkConfigSHA256(ctx)
return r, nil
}
// This is a remote path lookup.
if !strings.Contains(remote, "://") { // No URL scheme, could be host:path
if strings.Contains(remote, ":") {
return nil, fmt.Errorf("git remote (%s) must not be local directory (use URL syntax not host:path syntax)", remote)
}
return nil, fmt.Errorf("git remote (%s) must not be local directory", remote)
}
var err error
r.dir, r.mu.Path, err = WorkDir(ctx, gitWorkDirType, r.remote)
if err != nil {
return nil, err
}
unlock, err := r.mu.Lock()
if err != nil {
return nil, err
}
defer unlock()
if _, err := os.Stat(filepath.Join(r.dir, "objects")); err != nil {
repoSha256Hash := false
if refs, lrErr := r.loadRefs(ctx); lrErr == nil {View on GitHub (pinned to b6b368adc5)
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.
Example fix
// before (go.mod) replace example.com/mod => git@github.com:owner/repo.git // after replace example.com/mod => ssh://git@github.com/owner/repo.git
Defensive patterns
Strategy: validation
Validate before calling
func normalizeGitRemote(remote string) (string, error) {
if strings.Contains(remote, "://") {
return remote, nil // already a URL
}
// Detect SCP-style host:path
if idx := strings.Index(remote, ":"); idx > 0 {
host := remote[:idx]
path := remote[idx+1:]
return "ssh://" + host + "/" + path, nil
}
return "", fmt.Errorf("%q has no URL scheme and is not SCP-style", remote)
} Type guard
null
Try / catch
null
Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- git remote (%s) lookup disabled
- git remote (%s) must not be local directory
- %s exists but is not a directory
- revision does not exist locally: %s
- path is not absolute
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/39b6a9dbb8a8ada3.
Report an issue: GitHub.