golang/go · error

multiple VCS detected: %s in %q, and %s in %q

Error message

multiple VCS detected: %s in %q, and %s in %q

What it means

As a security mitigation against VCS injection attacks, FromDir stops if it encounters two different VCS root types in the directory hierarchy (e.g., a .svn directory inside a .git working copy). The only exceptions are nested Git (submodules) and the experimental GODEBUG=allowmultiplevcs=1 flag.

Source

Thrown at src/cmd/go/internal/vcs/vcs.go:522

					vcsCmd = vcs
					repoDir = dir
					if allowmultiplevcs.Value() == "1" {
						allowmultiplevcs.IncNonDefault()
						return repoDir, vcsCmd, nil
					}
					// If allowmultiplevcs is not set, keep looking for
					// repositories in current and parent directories and report
					// an error if one is found to mitigate VCS injection
					// attacks.
					continue
				}
				if vcsCmd == vcsGit && vcs == vcsGit {
					// Nested Git is allowed, as this is how things like
					// submodules work. Git explicitly protects against
					// injection against itself.
					continue
				}
				return "", nil, fmt.Errorf("multiple VCS detected: %s in %q, and %s in %q",
					vcsCmd.Cmd, repoDir, vcs.Cmd, dir)
			}
		}

		// Move to parent.
		ndir := filepath.Dir(dir)
		if len(ndir) >= len(dir) {
			break
		}
		dir = ndir
	}
	if vcsCmd == nil {
		return "", nil, &vcsNotFoundError{dir: origDir}
	}
	return repoDir, vcsCmd, nil
}

// isVCSRootDir reports whether dir is a VCS root according to roots.

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Remove the extraneous VCS metadata directory (e.g., `rm -rf .svn` if you're actually using git)
  2. If nested repos are legitimate and non-Git, set GODEBUG=allowmultiplevcs=1 (understand the security risk first)
  3. Audit the dependency tree for planted VCS directories if this is unexpected
  4. Re-clone the repository cleanly from a single VCS

Example fix

# before: both .git and .svn present
go build ./...  # multiple VCS detected

# after: remove the unwanted VCS metadata
rm -rf .svn
go build ./...
Defensive patterns

Strategy: validation

Validate before calling

# Check for multiple VCS metadata directories before building
VCS_DIRS="$(find . -maxdepth 2 \( -name .git -o -name .hg -o -name .svn -o -name .bzr -o -name .fslckout \) -print 2>/dev/null | sort -u)"
COUNT=$(echo "$VCS_DIRS" | grep -c . || true)
if [ "$COUNT" -gt 1 ]; then
  echo "WARNING: multiple VCS directories found:"
  echo "$VCS_DIRS"
  echo 'Remove extraneous VCS metadata to avoid injection detection'
fi

Try / catch

# Detect multiple VCS error and report
ERR=$(go build ./... 2>&1)
if echo "$ERR" | grep -q 'multiple VCS detected'; then
  echo 'Multiple VCS metadata dirs found — remove the unwanted one'
  echo 'Or set GODEBUG=allowmultiplevcs=1 if you understand the risk'
fi

Prevention

When it happens

Trigger: A package directory tree contains VCS metadata from two different systems — e.g., `.hg` inside a `.git` repo, or `.svn` alongside `.git`. Also triggered by a malicious package planting a foreign VCS metadata directory to redirect fetching.

Common situations: Converting a repo from one VCS to another without cleaning up old metadata; nested checkouts from different VCS systems; supply-chain attack where a dependency includes a planted .hg/.svn directory.

Related errors


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