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
- Ensure every commandId passed to register is of the form `${pluginId}.${localName}`.
- Derive the prefix from the same callerId used in activate() — avoid hardcoding a different string.
- Add a unit test asserting all registered IDs start with the plugin's own id.
- 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
- Derive command IDs from the same callerId string used in activate().
- Add a unit test asserting every registered command starts with `${pluginId}.`.
- Use the cross-plugin execute() path to invoke other plugins' commands, never register().
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
- plugin.command.not_declared_in_manifest
- plugin.commands.not_found
- plugin.commands.access_denied
- PluginRuntimeFault
- PluginRuntimeFault
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/ae13494c05736dd9.
Report an issue: GitHub.