can1357/oh-my-pi · error · Error
Plugin "${pluginId}" is not installed in project scope
Error message
Plugin "${pluginId}" is not installed in project scope What it means
MarketplaceManager.uninstallPlugin() resolves which registry (user-level or project-level) holds the plugin before removing it. This error is thrown when the caller explicitly passed scope="project", but the plugin id was only found in the user-scope installed-plugins registry, so uninstalling from project scope is impossible. It prevents silently modifying the wrong registry or removing a plugin that is not actually installed where the user asked.
Source
Thrown at packages/coding-agent/src/extensibility/plugins/marketplace/manager.ts:476
}
// 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;
}
const updatedReg = removeInstalledPlugin(targetReg, pluginId);
await writeInstalledPluginsRegistry(registryPath, updatedReg);
// Read both registries AFTER removal — only delete paths no longer referenced by either.
const [freshUserReg, freshProjectReg] = await Promise.all([View on GitHub (pinned to 9690622007)
Solutions
- Re-run without the --scope flag so the manager auto-targets the scope where the plugin is actually installed.
- Re-run with `--scope user` to uninstall from the user registry where the plugin is actually recorded.
- Verify where the plugin is installed with `omp plugin list` (it shows per-scope entries) before specifying a scope.
Example fix
// before
await manager.uninstallPlugin("formatter@team", "project");
// after
await manager.uninstallPlugin("formatter@team", "user"); // or omit scope to auto-resolve Defensive patterns
Strategy: validation
Validate before calling
import { MarketplaceManager } from "./manager";
const installed = await manager.listInstalledPlugins();
const entry = installed.find(p => p.id === pluginId);
if (!entry) throw new Error(`Plugin ${pluginId} is not installed`);
if (scope === "project" && entry.scope !== "project") {
scope = entry.scope; // retarget to the scope where it actually lives
} Type guard
function isInScope(entry: { id: string; scope: "user" | "project" } | undefined, scope: "user" | "project"): entry is { id: string; scope: "user" | "project" } {
return entry !== undefined && entry.scope === scope;
} Try / catch
try {
await manager.uninstallPlugin(pluginId, "project");
} catch (err) {
if (err instanceof Error && err.message.includes('is not installed in project scope')) {
await manager.uninstallPlugin(pluginId); // let the manager resolve the scope
} else throw err;
} Prevention
- Call listInstalledPlugins() and inspect the returned scope before passing an explicit scope.
- Omit the scope argument whenever only one installation exists; pass it only after a both-scopes conflict.
- Keep CLI scripts free of hardcoded --scope values copied from other machines.
When it happens
Trigger: Calling `uninstallPlugin(pluginId, "project")` (or the equivalent `omp plugin uninstall <id> --scope project` CLI path) when `#findInBothRegistries(pluginId)` returns projectEntries empty/undefined but userEntries non-empty.
Common situations: The plugin was installed with `plugin install --scope user` (the default for personal setups) but the uninstall command repeats `--scope project` copied from a teammate or CI script; the project-local registry file (e.g. .omp/plugins in the repo) was deleted or the command is run outside the project directory, so only the user registry still lists the plugin.
Related errors
- Plugin "${pluginId}" is installed in both user and project s
- Plugin ${name} not found in runtime config
- Unknown feature "${feat}" in ${name}. Available: ${Object.ke
- Invalid marketplace name for cache: "${marketplace}"
- Invalid plugin name for cache: "${pluginName}"
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/4b384fe2ab5ac2e4.
Report an issue: GitHub.