agalwood/Motrix · error · CommandsError

plugin.commands.id_out_of_namespace

plugin.commands.id_out_of_namespace

Error message

command "${commandId}" is outside namespace "${callerId}." — commands must start with "${callerId}."

What it means

CommandsError with code 'plugin.commands.id_out_of_namespace', thrown by CommandsCapabilityHost.register when commandId does not start with `${callerId}.`. The capability enforces namespacing so a plugin can only register commands it owns (spec §5 L1741-1746), preventing one plugin from shadowing another's command IDs. callerId is the plugin's own identifier.

Source

Thrown at src/core/plugin/capabilities/commands.ts:114

  /**
   * Register `handler` for `commandId`. The `commandId` MUST start with
   * `${callerId}.` — i.e. belong to the caller's own namespace. When a
   * manifest resolver is configured, `commandId` must also be declared in
   * the caller's `contributes.commands[]`. Returns a registration whose
   * `dispose()` removes only this command. Repeated registration of the
   * same id replaces the previous handler and emits `console.warn` (spec
   * §5 L1742, consistent with the hooks contract).
   *
   * @throws {CommandsError} plugin.commands.id_out_of_namespace — wrong owner
   * @throws {CommandsError} plugin.command.not_declared_in_manifest — missing from manifest
   */
  register(
    callerId: string,
    commandId: string,
    handler: CommandHandler
  ): CommandsRegistration {
    if (!commandId.startsWith(`${callerId}.`)) {
      throw new CommandsError(
        'plugin.commands.id_out_of_namespace',
        `command "${commandId}" is outside namespace "${callerId}." — commands must start with "${callerId}."`
      )
    }

    if (this.resolveDeclared) {
      const declared = this.resolveDeclared(callerId)
      if (!declared?.has(commandId)) {
        throw new CommandsError(
          'plugin.command.not_declared_in_manifest',
          `command "${commandId}" is not declared in plugin "${callerId}" manifest.contributes.commands[]`
        )
      }
    }

    if (this.handlers.has(commandId)) {
      console.warn(
        `[plugin:commands] handler for "${commandId}" registered more than once; previous handler replaced`

View on GitHub (pinned to 1a708ee577)

Solutions

  1. Ensure every commandId passed to register is of the form `${pluginId}.${localName}`.
  2. Derive the prefix from the same callerId used in activate() — avoid hardcoding a different string.
  3. Add a unit test asserting all registered IDs start with the plugin's own id.
  4. If you need to invoke another plugin's command, use the cross-plugin execute() path, not register().

Example fix

// before
host.register('myPlugin', 'doThing', handler)
// after
host.register('myPlugin', 'myPlugin.doThing', handler)
Defensive patterns

Strategy: validation

Validate before calling

function isInOwnNamespace(callerId: string, commandId: string): boolean {
  return commandId.startsWith(`${callerId}.`)
}
if (!isInOwnNamespace(callerId, commandId)) {
  throw new Error(`command ${commandId} must be in namespace ${callerId}.*`)
}
host.register(callerId, commandId, handler)

Type guard

function isInOwnNamespace(callerId: string, commandId: string): boolean {
  return commandId.startsWith(`${callerId}.`)
}

Try / catch

try {
  host.register(callerId, commandId, handler)
} catch (e) {
  if (e instanceof CommandsError && e.code === 'plugin.commands.id_out_of_namespace') {
    // fix the commandId prefix and retry
  } else throw e
}

Prevention

When it happens

Trigger: Calling host.register('myPlugin', 'otherPlugin.doThing', handler) — i.e. a plugin tries to register a command in another plugin's namespace, or in no namespace at all ('doThing' without a prefix). Also thrown if callerId is mistyped or empty so the prefix does not match.

Common situations: Copy-paste of a command ID from a different plugin; plugin id renamed but command IDs not updated; forgot to prefix with the plugin name; inconsistent callerId between activate() and register() (e.g. one uses 'foo', the other 'foo.bar').

Related errors


AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12). Data as JSON: /api/errors/ae13494c05736dd9. Report an issue: GitHub.