{"record":{"id":"1c40b49edf083d65","repo":"google-gemini/gemini-cli","slug":"cannot-update-to-newextensionname-because-an","errorCode":null,"errorMessage":"Cannot update to \"${newExtensionName}\" because an extension with that name is already installed.","messagePattern":"Cannot update to \"(.+?)\" because an extension with that name is already installed\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/config/extension-manager.ts","lineNumber":318,"sourceCode":"        const previous = this.getExtensions().find(\n          (installed) => installed.name === previousName,\n        );\n        const nameConflict = this.getExtensions().find(\n          (installed) =>\n            installed.name === newExtensionName &&\n            installed.name !== previousName,\n        );\n\n        if (isUpdate && !previous) {\n          throw new Error(\n            `Extension \"${previousName}\" was not already installed, cannot update it.`,\n          );\n        } else if (!isUpdate && previous) {\n          throw new Error(\n            `Extension \"${newExtensionName}\" is already installed. Please uninstall it first.`,\n          );\n        } else if (isUpdate && nameConflict) {\n          throw new Error(\n            `Cannot update to \"${newExtensionName}\" because an extension with that name is already installed.`,\n          );\n        }\n\n        const newHasHooks = fs.existsSync(\n          path.join(localSourcePath, 'hooks', 'hooks.json'),\n        );\n        const previousHasHooks = !!(\n          isUpdate &&\n          previous &&\n          previous.hooks &&\n          Object.keys(previous.hooks).length > 0\n        );\n\n        const newSkills = await loadSkillsFromDir(\n          path.join(localSourcePath, 'skills'),\n        );\n        const previousSkills = previous?.skills ?? [];","sourceCodeStart":300,"sourceCodeEnd":336,"githubUrl":"https://github.com/google-gemini/gemini-cli/blob/5024443c7217464a66e98f80d73172a26440bd8f/packages/cli/src/config/extension-manager.ts#L300-L336","documentation":"Thrown on the update path when the new manifest's `name` differs from `previousName` but a different already-installed extension already uses that new name. Renaming into a colliding namespace is refused to avoid two extensions claiming the same identity.","triggerScenarios":"Updating extension A so that its new version is named `B`, when extension `B` is already installed; a fork and its upstream both named identically and you update the fork to match upstream's name.","commonSituations":"Two related extensions (fork + upstream) installed side by side; an upstream rename that lands while a fork is also installed; merging extension manifests.","solutions":["Uninstall the extension that currently owns the target name before updating.","Keep the previous name to avoid the collision (do not rename the manifest).","Use distinct names across forks so updates never collide."],"exampleFix":"// before\nupdate extA v1 (name 'B') while extB exists  // collision\n// after\nuninstall extB; then update extA","handlingStrategy":"validation","validationCode":"const conflict = extensionManager\n  .getExtensions()\n  .find((e) => e.name === newExtensionName && e.name !== previousName);\nif (isUpdate && conflict) {\n  throw new Error(`Target name ${newExtensionName} already in use.`);\n}","typeGuard":"function renameCollides(newName: string, prevName: string, installed: { name: string }[]): boolean {\n  return newName !== prevName && installed.some((e) => e.name === newName);\n}","tryCatchPattern":null,"preventionTips":["Avoid renaming extensions across versions when a sibling already uses the target name.","Uninstall the colliding sibling before the rename-update.","Keep fork and upstream manifests under distinct names."],"tags":["extensions","update","conflict"],"backgroundTag":null,"analyzedSha":"5024443c7217464a66e98f80d73172a26440bd8f","analyzedAt":"2026-08-12T06:01:53.711Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}