moeru-ai/airi · error · Error
Cannot declare permissions for unknown plugin "${extensionId
Error message
Cannot declare permissions for unknown plugin "${extensionId}". What it means
Thrown by `PermissionRegistry.declare()` when no permission snapshot exists in the store for the given `extensionId`. `declare()` is meant to amend an already-initialized plugin's requested permissions; it requires `initialize()` to have been called first for that extension id. The store lookup is the first operation, so any unknown extension id fails here before declaration merging.
Source
Thrown at packages/plugin-sdk/src/plugin-host/runtimes/shared/services/permissions.ts:322
const persisted = options?.persisted ?? {}
const explicitGrant = options?.grant ?? requested
const mergedGrant = mergePermissions(persisted, explicitGrant)
const granted = intersectPermissions(requested, mergedGrant)
const previousRevision = this.store.get(extensionId)?.revision ?? 0
const snapshot: PermissionSnapshot = {
requested,
granted,
revision: previousRevision + 1,
}
this.store.set(extensionId, snapshot)
return snapshot
}
declare(extensionId: string, requestedDeclaration: ModulePermissionDeclaration) {
const existing = this.store.get(extensionId)
if (!existing) {
throw new Error(`Cannot declare permissions for unknown plugin "${extensionId}".`)
}
const requested = normalizeDeclaration(requestedDeclaration)
const snapshot: PermissionSnapshot = {
requested: mergePermissionDeclarations(existing.requested, requested),
granted: existing.granted,
revision: existing.revision + 1,
}
this.store.set(extensionId, snapshot)
return snapshot
}
grant(extensionId: string, grant: ModulePermissionGrant) {
const existing = this.store.get(extensionId)
if (!existing) {
throw new Error(`Cannot grant permissions to unknown plugin "${extensionId}".`)
}View on GitHub (pinned to 27111382b4)
Solutions
- Call `permissions.initialize(extensionId, requestedDeclaration)` once before any `declare()` or `grant()` for that extension.
- Verify the `extensionId` argument exactly matches the id used at initialization (same casing, scope, no trailing whitespace).
- Guard with `permissions.get(extensionId)` before calling `declare()`, and initialize on demand if missing.
- If the store was reset (reload, test isolation), re-run the full initialization sequence, not just declare.
Example fix
// before
permissions.declare(extensionId, declaration)
// after
if (!permissions.get(extensionId)) {
permissions.initialize(extensionId, declaration)
} else {
permissions.declare(extensionId, declaration)
} Defensive patterns
Strategy: validation
Validate before calling
if (!permissions.get(extensionId)) {
permissions.initialize(extensionId, requestedDeclaration)
} else {
permissions.declare(extensionId, requestedDeclaration)
} Type guard
function isPermissionInitialized(extensionId: string): boolean {
return permissions.get(extensionId) !== undefined
} Try / catch
try {
permissions.declare(extensionId, requestedDeclaration)
} catch (e) {
if (e instanceof Error && e.message.includes('Cannot declare permissions for unknown plugin')) {
permissions.initialize(extensionId, requestedDeclaration)
return
}
throw e
} Prevention
- Establish a strict bootstrap order: initialize every extension's permissions before any declare/grant call.
- Share a single normalized extension id between registration and permission calls.
- After a store reset, replay the full initialize sequence, not just incremental ops.
- Guard declare/grant with permissions.get(extensionId) in code paths that may run out of order.
When it happens
Trigger: Calling `permissions.declare(extensionId, declaration)` for an extension that has not yet been registered via `permissions.initialize(extensionId, ...)`. Also triggered after a registry reset/clear, by a typo in the extension id, or by out-of-order host wiring that declares permissions before the extension registration step completes.
Common situations: Plugin host bootstrap that calls `declare()` before `initialize()`; extension ids that differ between registration and declaration (e.g. name vs. scoped id); reloading a plugin into a fresh permission store without re-initializing; tests that exercise declare without seeding the store.
Related errors
- Cannot grant permissions to unknown plugin "${extensionId}".
- Permission denied: ${details.area}.${details.action} "${deta
- Module `${moduleId}` was not found.
- Godot stage is not running.
- Godot stage bridge is not connected.
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/1b7d8525b02e11ca.
Report an issue: GitHub.