RocketChat/Rocket.Chat · error · Error
The command is not currently disabled
Error message
The command is not currently disabled: "${cmd}" What it means
Rocket.Chat apps-engine apps can expose HTTP endpoints under /api/apps/private/:appId/:hash. AppApisBridge keeps one express Router per app (populated by registerApi when the app calls provideApi); if appId has no router, or the inner router matches no route for the path/method, the notFound fallback answers 404 'Not Found'.
Solutions
- Verify the app is installed and enabled (Administration > Apps) and check the exact API path it exposes
- Confirm the app actually registers the endpoint (provideApi) and note the registered path and whether it expects auth
- Compare the appId in the URL with the app's ID shown in the admin Apps view
- Re-check the URL: correct appId, correct private hash segment, exact endpoint path and leading slash
Example fix
// before: endpoint never registered, client calls /api/apps/private/<appId>/<hash>/status -> 404
// after: app registers the endpoint
this.api = app.getLogger();
await app.getProviderManager().provideApi({ name: 'Status API', endpoints: [{ path: 'status', method: 'get', handler: async () => ({ status: 200, content: 'ok' } } as any) }] as any); Defensive patterns
Strategy: validation
Validate before calling
const res = await fetch(`${url}/api/apps/private/${appId}/${hash}/${path}`);
if (res.status === 404) throw new Error(`apps-engine endpoint not registered: app=${appId} path=${path} — verify install/enable state`); Type guard
const isRegisteredApp = (routers: Map<string, unknown>, appId: string): boolean => routers.has(appId);
Prevention
- Log the full appId/path on every 404 so misconfiguration is obvious
- Verify an app is installed and enabled before wiring external webhooks to its endpoints
- Pin endpoint paths in config and re-verify after app upgrades
- Include a health endpoint in every app that exposes an API
When it happens
Trigger: Calling /api/apps/private/<appId>/<hash>/... when the app is uninstalled or disabled; the app never called app.api.provideApi so no router exists; the endpoint path or method in the URL does not match what the app registered; wrong or malformed appId/hash segment shifting the parsed path.
Common situations: App removed or disabled while external integrations still call its endpoints; app upgraded and endpoint paths changed; app failed to build/enable after update; local development against a workspace where the app is not installed; URL-encoding problems corrupting :appId.
Related errors
- A new user type has been added that the Apps don't know…
- A video conference must exist to update.
- app-addon-not-valid
- App already exists.
- App could not be enabled
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/0ab6f0778ec838bd.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/app/apps/server/bridges/commands.ts:40
if (typeof command !== 'string' || command.length === 0) {
return false;
}
const cmd = command.toLowerCase();
return typeof slashCommands.commands[cmd] === 'object' || this.disabledCommands.has(cmd);
}
protected async enableCommand(command: string, appId: string): Promise<void> {
this.orch.debugLog(`The App ${appId} is attempting to enable the command: "${command}"`);
if (typeof command !== 'string' || command.trim().length === 0) {
throw new Error('Invalid command parameter provided, must be a string.');
}
const cmd = command.toLowerCase();
if (!this.disabledCommands.has(cmd)) {
throw new Error(`The command is not currently disabled: "${cmd}"`);
}
slashCommands.commands[cmd] = this.disabledCommands.get(cmd) as (typeof slashCommands.commands)[string];
this.disabledCommands.delete(cmd);
void this.orch.getNotifier().commandUpdated(cmd);
}
protected async disableCommand(command: string, appId: string): Promise<void> {
this.orch.debugLog(`The App ${appId} is attempting to disable the command: "${command}"`);
if (typeof command !== 'string' || command.trim().length === 0) {
throw new Error('Invalid command parameter provided, must be a string.');
}
const cmd = command.toLowerCase();
if (this.disabledCommands.has(cmd)) {
// The command is already disabled, no need to disable it yet againView on GitHub (pinned to b2c16d5842)