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
- Remove the extraneous VCS metadata directory (e.g., `rm -rf .svn` if you're actually using git)
- If nested repos are legitimate and non-Git, set GODEBUG=allowmultiplevcs=1 (understand the security risk first)
- Audit the dependency tree for planted VCS directories if this is unexpected
- 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
- Clean up old VCS metadata when migrating between systems
- Audit dependencies for planted VCS directories (supply-chain hygiene)
- Use a fresh single-VCS clone for builds
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
- leading hyphen
- invalid module version %q
- GOVCS disallows using %s for %s %s; see 'go help vcs'
- %s and %s disagree about go-import for %s
- %s: invalid subdirectory %q: %v
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/2209b08d333d55b2.
Report an issue: GitHub.