agalwood/Motrix · error · AppError
PluginManifestInvalid
PluginManifestInvalid
Error message
plugin.grants.unknown_plugin: ${pluginId} What it means
Thrown by GrantsManager.updateGrants when the registry has no entry for pluginId — i.e. the plugin is not discovered/registered. Grants can only be mutated for plugins the host knows about. Classified as PluginManifestInvalid because the install/discovery state is inconsistent with the request.
Source
Thrown at src/core/plugin/grants/grants-manager.ts:58
if (!record) return {}
return this.filterToOptional(pluginId, record.grants)
}
/**
* Apply a patch over the current grants and persist. Patch keys must be
* declared in `manifest.optionalPermissions`; unknown keys (including
* required permissions, which are never user-revocable) throw
* `plugin.grants.unknown_permission`. Builtins / dev plugins throw
* `plugin.grants.not_supported`.
*
* Emits `Events.PluginGrantsChanged` after the write; consumers
* (PluginHost in Phase 2) deactivate the plugin so the next activation
* picks up the new effective permissions.
*/
async updateGrants(pluginId: string, patch: GrantsMap): Promise<GrantsMap> {
const entry = this.opts.registry.get(pluginId)
if (!entry) {
throw new AppError(
ErrorCode.PluginManifestInvalid,
`plugin.grants.unknown_plugin: ${pluginId}`
)
}
if (entry.origin !== 'community' || entry.dev) {
throw new AppError(
ErrorCode.PluginPermissionUnsupported,
'plugin.grants.not_supported'
)
}
const optional = new Set(entry.manifest.optionalPermissions ?? [])
for (const key of Object.keys(patch)) {
if (!optional.has(key)) {
throw new AppError(
ErrorCode.PluginPermissionUnsupported,
`plugin.grants.unknown_permission: ${key}`
)View on GitHub (pinned to 1a708ee577)
Solutions
- Confirm the plugin is currently discovered: check registry.get(pluginId) or registry.entries() before calling updateGrants.
- Refresh the plugin list in the UI before allowing grants edits so stale ids are never sent.
- If the plugin was uninstalled, no grants mutation is meaningful — treat as a no-op or re-install first.
- Verify the exact id spelling against the manifest's id field.
Example fix
// before
await grants.updateGrants('acme.fetcher', { 'net.fetch': 'granted' })
// after
if (!registry.get('acme.fetcher')) throw new Error('plugin not installed')
await grants.updateGrants('acme.fetcher', { 'net.fetch': 'granted' }) Defensive patterns
Strategy: validation
Validate before calling
if (!registry.get(pluginId)) { throw new Error(`plugin ${pluginId} is not registered`) } Try / catch
try { await grants.updateGrants(pluginId, patch) }
catch (e) { if (e.message.startsWith('plugin.grants.unknown_plugin')) { /* refresh plugin list */ } else throw e } Prevention
- Refresh the discovered plugin list before allowing grants edits.
- Spell-check the id against the manifest.
- Don't send grants updates for uninstalled plugins.
When it happens
Trigger: Calling grantsManager.updateGrants(pluginId, patch) with an id that registry.get(pluginId) does not return — typo in the id, plugin not yet installed/discovered, or already uninstalled.
Common situations: A UI sends a grants update for a plugin id from a stale list (plugin was uninstalled since the list loaded), a developer typos the id, or the registry was reset/reloaded and the plugin hasn't been re-discovered yet.
Related errors
- PluginPermissionUnsupported
- PluginRuntimeFault
- plugin.capability.bad_args
- PLUGIN_MANIFEST_INVALID
- PLUGIN_MANIFEST_INVALID
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/63215ed525f7ca75.
Report an issue: GitHub.