{"record":{"id":"901d621532a65675","repo":"can1357/oh-my-pi","slug":"plugin-pluginid-is-installed-in-both-user-and","errorCode":null,"errorMessage":"Plugin \"${pluginId}\" is installed in both user and project scope. Use --scope user or --scope project to specify which to remove.","messagePattern":"Plugin \"(.+?)\" is installed in both user and project scope\\. Use --scope user or --scope project to specify which to remove\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/extensibility/plugins/marketplace/manager.ts","lineNumber":464,"sourceCode":"\tasync uninstallPlugin(pluginId: string, scope?: \"user\" | \"project\", options?: { dryRun?: boolean }): Promise<void> {\n\t\tconst parsed = parsePluginId(pluginId);\n\t\tif (!parsed) {\n\t\t\tthrow new Error(`Invalid plugin ID format: \"${pluginId}\". Expected \"name@marketplace\".`);\n\t\t}\n\n\t\tconst { userEntries, projectEntries, userReg, projectReg } = await this.#findInBothRegistries(pluginId);\n\t\tconst inUser = userEntries && userEntries.length > 0;\n\t\tconst inProject = projectEntries && projectEntries.length > 0;\n\n\t\tif (!inUser && !inProject) {\n\t\t\tthrow new Error(`Plugin \"${pluginId}\" is not installed`);\n\t\t}\n\n\t\t// Disambiguation: if installed in both scopes and no explicit scope, require one.\n\t\tlet targetScope: \"user\" | \"project\";\n\t\tif (inUser && inProject) {\n\t\t\tif (!scope) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Plugin \"${pluginId}\" is installed in both user and project scope. Use --scope user or --scope project to specify which to remove.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\ttargetScope = scope;\n\t\t} else if (inProject) {\n\t\t\tif (scope === \"user\") {\n\t\t\t\tthrow new Error(`Plugin \"${pluginId}\" is not installed in user scope`);\n\t\t\t}\n\t\t\ttargetScope = \"project\";\n\t\t} else {\n\t\t\tif (scope === \"project\") {\n\t\t\t\tthrow new Error(`Plugin \"${pluginId}\" is not installed in project scope`);\n\t\t\t}\n\t\t\ttargetScope = \"user\";\n\t\t}\n\n\t\tconst targetEntries = targetScope === \"project\" ? projectEntries! : userEntries!;\n\t\tconst targetReg = targetScope === \"project\" ? projectReg : userReg;","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/extensibility/plugins/marketplace/manager.ts#L446-L482","documentation":"When a plugin id exists in both the user-scope and project-scope registries, uninstallPlugin refuses to guess which copy to remove and demands an explicit scope argument. This protects users from deleting the wrong installation when the same plugin is installed at both levels.","triggerScenarios":"uninstallPlugin(pluginId) with no scope argument (or scope: undefined) while the id resolves to entries in both the user registry and the project registry.","commonSituations":"Installing a plugin globally early on and later also project-locally for pinning; scripts written before the plugin appeared in both scopes; interactive use where the user did not know about dual installation.","solutions":["Pass the scope explicitly: uninstallPlugin(id, \"user\") or uninstallPlugin(id, \"project\")","Decide which copy you want to keep and remove only the other scope","Run uninstall twice with each scope if you want both removed","Check both registries first to confirm what each scope holds"],"exampleFix":"// before\nawait manager.uninstallPlugin(\"formatter@community\");\n// after\nawait manager.uninstallPlugin(\"formatter@community\", \"project\"); // or \"user\"","handlingStrategy":"try-catch","validationCode":"const userCopy = await manager.listInstalledPlugins(\"user\");\nconst projCopy = await manager.listInstalledPlugins(\"project\");\nconst inBoth = userCopy.some(p => p.id === pluginId) && projCopy.some(p => p.id === pluginId);\nawait manager.uninstallPlugin(pluginId, inBoth ? desiredScope : undefined);","typeGuard":null,"tryCatchPattern":"try {\n  await manager.uninstallPlugin(pluginId, scope); // scope may be undefined\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"installed in both user and project scope\")) {\n    await manager.uninstallPlugin(pluginId, await askUserToPickScope());\n  } else throw err;\n}","preventionTips":["Always pass an explicit scope in scripts so behavior never depends on registry state","Avoid installing the same plugin at both scopes; pick one convention per team","Check both registries before uninstall to know whether disambiguation is needed","In interactive CLIs, prompt for scope on this error instead of failing"],"tags":["plugin-marketplace","ambiguity","scope"],"backgroundTag":"ambiguous-scope-requires-explicit-scope","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}