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

  1. Call `permissions.initialize(extensionId, requestedDeclaration)` once before any `declare()` or `grant()` for that extension.
  2. Verify the `extensionId` argument exactly matches the id used at initialization (same casing, scope, no trailing whitespace).
  3. Guard with `permissions.get(extensionId)` before calling `declare()`, and initialize on demand if missing.
  4. 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

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


AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12). Data as JSON: /api/errors/1b7d8525b02e11ca. Report an issue: GitHub.