Most broken submodules come down to one of three states: the index holds a gitlink that .gitmodules no longer describes, .gitmodules describes a submodule whose repository is missing from .git/modules/, or a path is already occupied when you try to add it again. Each state has its own error message and its own fix. Every message and command below was reproduced on Git 2.50.1.

fatal: No url found for submodule path '<path>' in .gitmodules

The index still carries a gitlink at <path>, but .gitmodules has no url for it. This usually follows a merge that dropped the entry, or a manual edit.

Restore the url and push it into the local config:

git config -f .gitmodules submodule.<name>.url <repository-url>
git submodule sync -- <path>
git submodule update --init -- <path>

<name> is the name inside [submodule "<name>"], which defaults to the path but does not have to match it. The sync step matters: it copies the url from .gitmodules into .git/config, and without it Git keeps using the old value.

fatal: no submodule mapping found in .gitmodules for path '<path>'

The same root cause seen from a different command. Here the whole [submodule] block is gone while the gitlink remains in the index, and git submodule status is what reports it. In that same state git submodule update --init prints the previous message instead, a bare git submodule update exits quietly with nothing at all, and git rm --cached <path> just succeeds, so the command you happened to run decides what you see.

If the submodule is supposed to stay, restore its block and follow the previous section. If it is meant to be gone, drop the gitlink:

git add .gitmodules
git rm --cached <path>
git commit -m "drop stale submodule"

The git add is not optional. With unstaged edits in .gitmodules, git rm --cached refuses with fatal: please stage your changes to .gitmodules or stash them to proceed. The files stay on disk as untracked afterwards, so delete the directory separately if you do not want them.

fatal: could not get a repository handle for submodule '<path>'

The mapping is correct, but Git cannot open the submodule repository, because .git/modules/<name> is missing or corrupt.

git submodule deinit -f -- <path>
git submodule update --init --recursive -- <path>

fatal: '<path>' already exists in the index

git submodule add refuses because something is already tracked at that path: a gitlink from an earlier attempt, or an ordinary directory that was committed there. Clear all three places before adding again, the index, the internal repository and the working directory:

git rm --cached <path>
rm -rf .git/modules/<name>
rm -rf <path>
git submodule add <repository-url> <path>

Do all three. Drop only the index entry and git submodule add quietly re-adopts the repository still sitting there, reporting Adding existing repo at '<path>' to the index, which looks like success and reinstates whatever was broken. Drop the index entry and .git/modules/<name> but leave the directory, and you get fatal: '<path>' already exists and is not a valid git repo.

General repair procedure

When the message does not match any of the above, walk the state from the outside in.

🧐 Verify .gitmodules Configuration

Ensure that the .gitmodules file exists and contains the correct reference:

cat .gitmodules

Expected output:

[submodule "submodule-name"]
    path = path/to/submodule
    url = https://github.com/user/repo.git

🔍 Check Submodule Status

Determine whether the submodule is recognised by Git:

git submodule status

If the submodule appears but is not initialized, proceed with the next steps.

🔄 Reinitialize Submodules

Fetch and initialize the submodule:

git submodule update --init --recursive

If the submodule directory is missing or broken, continue with the reset process.

🚫 Remove Broken Submodule Reference

If the submodule is improperly linked, remove its reference:

rm -rf path/to/submodule
git config --remove-section submodule.path/to/submodule || true
git rm --cached path/to/submodule

➕ Re-add the Submodule

Reintroduce the submodule:

git submodule add https://github.com/user/repo.git path/to/submodule

🔄 Finalise the Update

Ensure all submodules are properly initialized:

git submodule update --init --recursive

🗂 Verify .git/modules/ Directory

If issues persist, check whether the submodule is listed in .git/modules/:

ls -la .git/modules

If a corresponding directory exists but is corrupt, remove and reinitialize it.

These steps should restore the correct submodule linkage in your Git repository.