google-gemini/gemini-cli · error · Error
Unable to find any remotes for repo ${installMetadata.source
Error message
Unable to find any remotes for repo ${installMetadata.source} What it means
Thrown by cloneFromGit() after git.clone succeeds but git.getRemotes(true) returns an empty array. A normal clone registers an 'origin' remote, so zero remotes indicates the clone did not actually fetch a real repository (empty repo, intercepted clone, or a source that produced a working tree without remote config).
Source
Thrown at packages/cli/src/config/extensions/github.ts:60
if (
parsedUrl.protocol === 'https:' &&
parsedUrl.hostname === 'github.com'
) {
if (!parsedUrl.username) {
parsedUrl.username = token;
}
sourceUrl = parsedUrl.toString();
}
} catch {
// If source is not a valid URL, we don't inject the token.
// We let git handle the source as is.
}
}
await git.clone(sourceUrl, './', ['--depth', '1']);
const remotes = await git.getRemotes(true);
if (remotes.length === 0) {
throw new Error(
`Unable to find any remotes for repo ${installMetadata.source}`,
);
}
const refToFetch = installMetadata.ref || 'HEAD';
await git.fetch(remotes[0].name, refToFetch);
// After fetching, checkout FETCH_HEAD to get the content of the fetched ref.
// This results in a detached HEAD state, which is fine for this purpose.
await git.checkout('FETCH_HEAD');
} catch (error) {
throw new Error(
`Failed to clone Git repository from ${installMetadata.source} ${getErrorMessage(error)}`,
{
cause: error,
},
);View on GitHub (pinned to 5024443c72)
Solutions
- Verify the source repository is non-empty and the token (getGitHubToken) grants read access.
- Retry the clone; transient empty-remote results can occur under network instability.
- If maintaining a custom mirror, ensure an 'origin' remote is configured with git remote add.
Example fix
// before
const remotes = await git.getRemotes(true);
if (remotes.length === 0) throw new Error(...);
// after
const remotes = await git.getRemotes(true);
if (remotes.length === 0) {
await git.addRemote('origin', installMetadata.source);
remotes = await git.getRemotes(true);
} Defensive patterns
Strategy: retry
Validate before calling
async function hasRemotes(dest: string): Promise<boolean> {
const g = simpleGit(dest); const r = await g.getRemotes(true); return r.length > 0;
} Try / catch
try { await cloneFromGit(meta, dest); } catch (e) { if (/Unable to find any remotes/.test(String(e))) { await simpleGit(dest).addRemote('origin', meta.source); /* retry once */ await cloneFromGit(meta, dest); } else throw e; } Prevention
- Confirm the source repo is non-empty and reachable before cloning.
- In tests, ensure the mocked clone registers an origin remote.
When it happens
Trigger: cloneFromGit installs an extension whose source is an empty/private repo that clones but has no configured remote, or an environment where the clone is stubbed/mocked and returns no remote metadata.
Common situations: Private repo returning an empty clone due to partial auth; a mirror or bundled repo without remote config; CI with a git cache/shallow clone that strips remote metadata; flaky networks where getRemotes returns [] transiently.
Related errors
- Failed to clone Git repository from ${installMetadata.source
- Installing extensions from remote sources is disallowed by y
- Failed to install extension ${installMetadata.source}: ${res
- Invalid repo URL: ${source}
- Invalid GitHub repository source: ${source}. Expected "owner
AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12).
Data as JSON: /api/errors/0ac11ee9688bbf9e.
Report an issue: GitHub.