google-gemini/gemini-cli · error · Error
Extension "${newExtensionName}" is already installed. Please
Error message
Extension "${newExtensionName}" is already installed. Please uninstall it first. What it means
Thrown on the fresh-install path (`isUpdate` is false) when an extension with the same `newExtensionName` is already loaded. The manager refuses to overwrite an installed extension silently; the user must uninstall first.
Source
Thrown at packages/cli/src/config/extension-manager.ts:314
newExtensionConfig = await this.loadExtensionConfig(localSourcePath);
const newExtensionName = newExtensionConfig.name;
const previousName = previousExtensionConfig?.name ?? newExtensionName;
const previous = this.getExtensions().find(
(installed) => installed.name === previousName,
);
const nameConflict = this.getExtensions().find(
(installed) =>
installed.name === newExtensionName &&
installed.name !== previousName,
);
if (isUpdate && !previous) {
throw new Error(
`Extension "${previousName}" was not already installed, cannot update it.`,
);
} else if (!isUpdate && previous) {
throw new Error(
`Extension "${newExtensionName}" is already installed. Please uninstall it first.`,
);
} else if (isUpdate && nameConflict) {
throw new Error(
`Cannot update to "${newExtensionName}" because an extension with that name is already installed.`,
);
}
const newHasHooks = fs.existsSync(
path.join(localSourcePath, 'hooks', 'hooks.json'),
);
const previousHasHooks = !!(
isUpdate &&
previous &&
previous.hooks &&
Object.keys(previous.hooks).length > 0
);
View on GitHub (pinned to 5024443c72)
Solutions
- Uninstall the existing extension first: `gemini extensions uninstall <name>`.
- If you want to switch sources, pass `previousExtensionConfig` so the call is treated as an update rather than a fresh install.
- Confirm the manifest `name` field is unique across installed extensions.
Example fix
// before $ gemini extensions install owner/repo-fork # name collides with installed // after $ gemini extensions uninstall my-ext && gemini extensions install owner/repo-fork
Defensive patterns
Strategy: validation
Validate before calling
const installed = extensionManager.getExtensions();
if (!isUpdate && installed.some((e) => e.name === newExtensionName)) {
throw new Error(`${newExtensionName} already installed. Uninstall first.`);
} Type guard
function nameIsFree(name: string, installed: { name: string }[]): boolean {
return !installed.some((e) => e.name === name);
} Prevention
- Check `getExtensions()` before issuing a fresh install.
- Keep a single canonical source per extension `name`.
- Uninstall before switching sources to keep state consistent.
When it happens
Trigger: Running `gemini extensions install owner/repo` for an extension whose manifest `name` collides with an already-installed one; reinstalling from a different source without uninstalling first.
Common situations: Installing the same extension from two different URLs/forks; a renamed source that ships the same `name` field in its manifest; reinstalling after a partial failure that left the prior install loaded.
Related errors
- Cannot install extension "${newExtensionName}" because a dir
- Installation aborted: Folder "${absolutePath}" is not truste
- The source argument must be provided.
- Failed to install extension ${installMetadata.source}: ${res
- Unsupported install type: ${installMetadata.type}
AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12).
Data as JSON: /api/errors/e50c91c5fbab9b14.
Report an issue: GitHub.