golang/go · error

invalid vcs remote: %s %s

Error message

invalid vcs remote: %s %s

What it means

In non-local mode, newVCSRepo requires the remote string to contain '://' so that WorkDir can treat it as a URL. A remote without a scheme separator (e.g. 'git@host:path', a bare path, or a misspelled URL) is rejected. The %s pair is the vcs name and the malformed remote.

Source

Thrown at src/cmd/go/internal/modfetch/codehost/vcs.go:119

	cmd := vcsCmds[vcs]
	if cmd == nil {
		return nil, fmt.Errorf("unknown vcs: %s %s", vcs, remote)
	}
	r.cmd = cmd
	if local {
		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"
		return r, nil
	}
	if !strings.Contains(remote, "://") {
		return nil, fmt.Errorf("invalid vcs remote: %s %s", vcs, remote)
	}
	var err error
	r.dir, r.mu.Path, err = WorkDir(ctx, vcsWorkDirType+vcs, r.remote)
	if err != nil {
		return nil, err
	}

	if cmd.init == nil {
		return r, nil
	}

	unlock, err := r.mu.Lock()
	if err != nil {
		return nil, err
	}
	defer unlock()

	if _, err := os.Stat(filepath.Join(r.dir, "."+vcs)); err != nil {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Use a fully-qualified URL with scheme: https://, http://, ssh://, git://, file://.
  2. Fix the go-import meta tag on the vanity server to emit the scheme.
  3. For ssh remotes, expand SCP-style syntax to ssh://git@host/path before it reaches the go command.
  4. If a local path is intended, use the local-mode (file://) or a replace directive instead.

Example fix

<!-- before -->
<meta name="go-import" content="example.org/m mod git.example.org/m">

<!-- after -->
<meta name="go-import" content="example.org/m mod https://git.example.org/m">
Defensive patterns

Strategy: validation

Validate before calling

func remoteHasScheme(remote string) bool {
    return strings.Contains(remote, "://")
}

// expand SCP-style ssh first if needed:
func normaliseSSH(remote string) string {
    if strings.HasPrefix(remote, "git@") && strings.Contains(remote, ":") {
        return "ssh://" + strings.Replace(remote, ":", "/", 1)
    }
    return remote
}

Prevention

When it happens

Trigger: newVCSRepo with local==false and a remote string lacking '://' — typical with SCP-style ssh ('git@github.com:org/repo') or a relative path passed where an absolute URL was expected.

Common situations: A vanity go-import meta tag missing the scheme ('git.example.org/repo' instead of 'https://git.example.org/repo'); copy-pasted ssh alias syntax; a corrupted module cache record storing a bare path.

Related errors


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