can1357/oh-my-pi · error · Error

Plugin "${pluginId}" is not installed in user scope

Error message

Plugin "${pluginId}" is not installed in user scope

What it means

During scope resolution, if the plugin is installed only in project scope but the caller explicitly requested scope "user", uninstallPlugin throws this mismatch error rather than silently uninstalling nothing or targeting the wrong scope. (The mirror error exists for scope "project" when only user-scope install exists.)

Source

Thrown at packages/coding-agent/src/extensibility/plugins/marketplace/manager.ts:471

		const inUser = userEntries && userEntries.length > 0;
		const inProject = projectEntries && projectEntries.length > 0;

		if (!inUser && !inProject) {
			throw new Error(`Plugin "${pluginId}" is not installed`);
		}

		// Disambiguation: if installed in both scopes and no explicit scope, require one.
		let targetScope: "user" | "project";
		if (inUser && inProject) {
			if (!scope) {
				throw new Error(
					`Plugin "${pluginId}" is installed in both user and project scope. Use --scope user or --scope project to specify which to remove.`,
				);
			}
			targetScope = scope;
		} else if (inProject) {
			if (scope === "user") {
				throw new Error(`Plugin "${pluginId}" is not installed in user scope`);
			}
			targetScope = "project";
		} else {
			if (scope === "project") {
				throw new Error(`Plugin "${pluginId}" is not installed in project scope`);
			}
			targetScope = "user";
		}

		const targetEntries = targetScope === "project" ? projectEntries! : userEntries!;
		const targetReg = targetScope === "project" ? projectReg : userReg;
		const registryPath = this.#registryPath(targetScope);
		const packageNames = await this.#resolveInstalledPackageNames(targetEntries, parsed.name);

		if (options?.dryRun) {
			return;
		}

View on GitHub (pinned to 9690622007)

Solutions

  1. Retry with the matching scope: uninstallPlugin(pluginId, "project")
  2. Omit the scope if only one installation exists and you want that one removed
  3. Confirm the installation scope via the plugin list before specifying --scope
  4. If you intended a user-scope install, install it at user scope first — there is nothing at user scope to remove

Example fix

// before
await manager.uninstallPlugin("formatter@community", "user");
// after
await manager.uninstallPlugin("formatter@community", "project"); // plugin is project-scoped only
Defensive patterns

Strategy: validation

Validate before calling

const inUser = (await manager.listInstalledPlugins("user")).some(p => p.id === pluginId);
const inProject = (await manager.listInstalledPlugins("project")).some(p => p.id === pluginId);
if (!inUser && !inProject) return; // nothing installed
await manager.uninstallPlugin(pluginId, inUser ? "user" : "project");

Try / catch

try {
  await manager.uninstallPlugin(pluginId, scope);
} catch (err) {
  if (err instanceof Error && err.message.includes("is not installed in")) {
    // wrong scope requested; fall back to the scope that actually has it
    await manager.uninstallPlugin(pluginId, err.message.includes("user scope") ? "project" : "user");
  } else throw err;
}

Prevention

When it happens

Trigger: uninstallPlugin(pluginId, "user") where #findInBothRegistries found entries only in the project registry (inProject true, inUser false).

Common situations: CLI users passing --scope user out of habit when the plugin was project-installed; automation hardcoding one scope; a teammate installed the plugin at project level but you assumed it was your user-level install.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/66334509e3d840cc. Report an issue: GitHub.