▲11 ▼0 @backtracker 2026-08-31 git submodules ci

git submodule "fatal: repository not found" on a fresh clone: the URL the submodule recorded is not the URL you think

verbatim errorCloning into '/build/vendor/common-lib'... fatal: repository 'https://github.com/acme/common-lib.git/' not found fatal: could not fetch commit 3f9c1d2 from submodule path 'vendor/common-lib'

Problem

CI clones the repo with --recurse-submodules and dies:

Cloning into '/build/vendor/common-lib'... fatal: repository 'https://github.com/acme/common-lib.git/' not found fatal: could not fetch commit 3f9c1d2 from submodule path 'vendor/common-lib'

The repo exists. Cloning it by hand works. The failure reproduces on every CI run and on one teammate's machine but not another's.

Root cause

.gitmodules stores a literal URL, and the index stores whatever URL was current when the submodule was added. Common mismatches, all producing "not found":

1. The submodule was added via an SSH URL (git@github.com:acme/common-lib.git); CI runs without deploy keys, so auth fails — and for private repos GitHub reports auth failures as "not found". 2. The submodule was renamed/repo moved, and a teammate's checkout still has the old URL cached in their local config (.git/modules/vendor/common-lib/config), which is why it "works on my machine". 3. The org renamed and the recorded URL 404s for everyone, but nobody hit it because local clones already had the submodule populated.

The path that actually gets fetched comes from .git/config (local override) falling back to .gitmodules — so local state can mask a broken .gitmodules indefinitely.

fix preview — first 2 of 3 lines (bash), truncated:
git config --file .gitmodules --list git config --file .git/modules/vendor/common-lib/config submodule.vendor.url 2>/dev/null || true … 1 more line in the fix

🔒 the fix — including 4 code blocks — is members-only. $1/mo unlocks everything.

🔒 comments and voting are for members. $1/mo · every diagnosis is free to read, plus 3 complete sample fixes.