stablyai/orca · error · Error
cannot remove protected or non-installed plugin ${parsed.plu
Error message
cannot remove protected or non-installed plugin ${parsed.pluginKey} What it means
Thrown at plugins.ts:219-220 when canRemoveInstalledPlugin(pluginService, pluginKey, lock) returns false. That function (plugins.ts:79-88) returns true only if BOTH conditions hold: the plugin is not sourced as 'bundled' in the lockfile, AND the plugin is discovered and not marked isDev. So the error covers three distinct cases: the plugin is bundled/protected, it is a dev plugin, or it is not installed at all.
Source
Thrown at src/main/ipc/plugins.ts:220
pluginsDir,
url: parsed.url,
ref: parsed.ref,
hostVersion,
blockedPluginReason
})
if (result.ok) {
await pluginService.refresh()
}
return result
})
ipcMain.handle('plugins:remove', async (event, args: unknown) => {
await pluginService.whenReady()
const parsed = removeArgsSchema.parse(args)
const pluginsDir = getUserPluginsDir(pluginService.options.userDataPath)
const lock = await readPluginLockfile(pluginsDir)
if (!canRemoveInstalledPlugin(pluginService, parsed.pluginKey, lock)) {
throw new Error(`cannot remove protected or non-installed plugin ${parsed.pluginKey}`)
}
await pluginService.deactivatePlugin(parsed.pluginKey)
await removeInstalledPlugin({
pluginsDir,
pluginsDataDir: getPluginsDataDir(pluginService.options.userDataPath),
pluginKey: parsed.pluginKey
})
// Drop the stale consent so a later reinstall re-prompts from scratch.
const settings = store.getSettings()
const consents = { ...settings.pluginConsents }
delete consents[parsed.pluginKey]
const disabledPlugins = normalizePluginIdList(settings.disabledPlugins).filter(
(pluginKey) => pluginKey !== parsed.pluginKey
)
store.updateSettings(
{ pluginConsents: consents, disabledPlugins },
{ notifyListeners: true, originWebContentsId: event.sender.id }
)View on GitHub (pinned to 1136503c6a)
Solutions
- Confirm the pluginKey exactly matches a discovered, non-dev, non-bundled plugin (check the plugins:list output).
- If it is a dev plugin, remove it by editing the devPluginPaths setting instead of calling plugins:remove.
- If it was already removed, no action is needed — refresh the plugin list.
- Bundled plugins cannot be removed by design; do not expose a remove affordance for them in the UI.
Defensive patterns
Strategy: type-guard
Validate before calling
// Before calling plugins:remove, check removability the same way the handler does.
const lock = await readPluginLockfile(getUserPluginsDir(userDataPath))
const removable =
lock?.plugins[pluginKey]?.source.kind !== 'bundled' &&
pluginService.getDiscovered().some((p) => p.pluginKey === pluginKey && !p.isDev)
if (!removable) { /* hide/disable the remove button */ } Type guard
function isRemovablePlugin(plugin: { isDev: boolean }, sourceKind?: string): boolean {
return !plugin.isDev && sourceKind !== 'bundled'
} Try / catch
try { await window.api.invoke('plugins:remove', { pluginKey }) }
catch (e) { if (e instanceof Error && e.message.startsWith('cannot remove protected or non-installed plugin')) { /* refresh list; it may already be gone */ } else throw e } Prevention
- Do not show a remove affordance for bundled or dev plugins in the UI.
- Refresh the discovered plugin list before offering remove, so the button reflects the current state.
- For dev plugins, guide users to edit devPluginPaths instead of removing.
When it happens
Trigger: Calling the plugins:remove IPC handler with a pluginKey that (a) is shipped/bundled with the app (lock.plugins[key].source.kind === 'bundled'), (b) is loaded from a dev path (plugin.isDev true), or (c) is not in the discovered plugin list (never installed or already removed).
Common situations: UI tries to show a remove button for a built-in plugin; a plugin was uninstalled out-of-band so the discovered list no longer has it; attempting to remove a dev plugin via the UI instead of editing devPluginPaths; typo in the pluginKey.
Related errors
- invalid_argument
- emulator_error
- Selected file is not a markdown document.
- ${label} is required
- ${label} is required
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/4f099bec9a31191a.
Report an issue: GitHub.