google-gemini/gemini-cli · error · Error

Cannot install extension

Error message

Cannot install extension "${newExtensionName}" because a directory with that name already exists. Please remove it manually.

What it means

Thrown when the computed destination directory (`ExtensionStorage(name).getExtensionDir()`) already exists on disk for a fresh install, or for an update that renames the extension. The manager will not overwrite an existing directory because it cannot safely attribute it.

Solutions

  1. Remove the destination directory manually and retry the install.
  2. Run `gemini extensions uninstall <name>` to let the manager clean it up.
  3. Check `~/.gemini/extensions/<name>` (and the workspace extensions dir) for stale folders.

Example fix

// before
$ gemini extensions install owner/repo  # dir exists
// after
$ rm -rf ~/.gemini/extensions/my-ext && gemini extensions install owner/repo
Defensive patterns

Strategy: validation

Validate before calling

const dest = new ExtensionStorage(newExtensionName).getExtensionDir();
if ((!isUpdate || newExtensionName !== previousName) && fs.existsSync(dest)) {
  throw new Error(`Destination ${dest} already exists; remove it manually.`);
}

Type guard

function destinationIsClear(dest: string): boolean {
  return !fs.existsSync(dest);
}

Prevention

When it happens

Trigger: A previous install/uninstall cycle left the directory behind; the user manually created a directory with the same name; a prior copy step was interrupted leaving a partial directory.

Common situations: Interrupted installs; partial uninstalls; manual `mkdir`/`cp` into the extensions dir; switching machines where half a directory was synced.

Related errors


AI-assisted analysis of google-gemini/gemini-cli@6a466a7e2f (2026-08-12). Data as JSON: /api/errors/687184dcd8bbf84e. Report an issue: GitHub.

Appendix: source

Thrown at packages/cli/src/config/extension-manager.ts:362

          newExtensionConfig,
          requestConsentOverride ?? this.requestConsent,
          newHasHooks,
          previousExtensionConfig,
          previousHasHooks,
          newSkills,
          previousSkills,
          isMigrating,
        );
        const extensionId = getExtensionId(newExtensionConfig, installMetadata);
        const destinationPath = new ExtensionStorage(
          newExtensionName,
        ).getExtensionDir();

        if (
          (!isUpdate || newExtensionName !== previousName) &&
          fs.existsSync(destinationPath)
        ) {
          throw new Error(
            `Cannot install extension "${newExtensionName}" because a directory with that name already exists. Please remove it manually.`,
          );
        }

        let previousSettings: Record<string, string> | undefined;
        let wasEnabledGlobally = false;
        let wasEnabledWorkspace = false;
        if (isUpdate && previousExtensionConfig) {
          const previousExtensionId = previous?.installMetadata
            ? getExtensionId(previousExtensionConfig, previous.installMetadata)
            : extensionId;
          previousSettings = await getEnvContents(
            previousExtensionConfig,
            previousExtensionId,
            this.workspaceDir,
          );
          if (newExtensionName !== previousName) {
            wasEnabledGlobally = this.extensionEnablementManager.isEnabled(

View on GitHub (pinned to 6a466a7e2f)