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

  1. Convert SCP syntax to a full URL: 'git@github.com:owner/repo.git' becomes 'ssh://git@github.com/owner/repo.git'.
  2. For replace directives, prefer filesystem paths for local development.
  3. Set GOPRIVATE and use 'GOFLAGS=-insecure' only if needed for plain-http (not SCP) cases.
  4. 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

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


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/39b6a9dbb8a8ada3. Report an issue: GitHub.