RocketChat/Rocket.Chat · error · Meteor.Error
error-not-allowed
error-not-allowed
Error message
Not allowed
What it means
saveCannedResponse (apps/meteor/ee/server/meteor-methods/saveCannedResponse.ts:23) requires the base 'save-canned-responses' permission via hasPermissionAsync; without it the call fails immediately with error-not-allowed before any argument validation runs.
Solutions
- Grant 'save-canned-responses' to the acting role (Administration > Permissions)
- Hide save/create UI for users without the permission
- For programmatic writes, use a service account that holds the permission
Example fix
// before
Meteor.call('saveCannedResponse', responseData);
// after
if (!(await hasPermissionAsync(uid, 'save-canned-responses'))) {
throw new Meteor.Error('error-not-allowed', 'Not allowed');
}
Meteor.call('saveCannedResponse', responseData); Defensive patterns
Strategy: validation
Validate before calling
if (!(await hasPermissionAsync(userId, 'save-canned-responses'))) {
throw new Meteor.Error('error-not-allowed', 'Not allowed');
}
await saveCannedResponse(userId, responseData, _id); Try / catch
try {
await saveCannedResponse(userId, responseData, _id);
} catch (e) {
if (e instanceof Meteor.Error && e.error === 'error-not-allowed') {
// hide save UI for this user; permissions missing
}
throw e;
} Prevention
- Gate the canned-response editor on 'save-canned-responses'
- Audit roles after enabling canned responses so agents get the intended permissions
- For programmatic writes, provision a service account with the permission
When it happens
Trigger: Calling saveCannedResponse with a userId lacking the 'save-canned-responses' permission — e.g. livechat agents without canned-response rights, or bots/integrations acting as unprivileged users.
Common situations: Canned responses enabled for the workspace but the agent's role was never granted the permission; permission set changed by an admin; custom automation using a plain user account.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- error-not-allowed
- error-canned-response-not-found
- error-action-not-allowed
- error-action-not-allowed
- error-action-not-allowed
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/d7f221152cc71229.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/ee/server/meteor-methods/saveCannedResponse.ts:23
import { hasPermissionAsync } from '../../../server/lib/authorization/hasPermission';
import notifications from '../../../server/lib/notifications/core/lib/Notifications';
type ResponseData = {
shortcut: string;
text: string;
scope: string;
tags?: string[];
departmentId?: string;
};
export const saveCannedResponse = async (
userId: string,
responseData: ResponseData,
_id?: string,
): Promise<Omit<IOmnichannelCannedResponse, '_updatedAt' | '_createdAt'> & { _createdAt?: Date }> => {
if (!(await hasPermissionAsync(userId, 'save-canned-responses'))) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'saveCannedResponse' });
}
check(_id, Match.Maybe(String));
check(responseData, {
shortcut: String,
text: String,
scope: String,
tags: Match.Maybe([String]),
departmentId: Match.Maybe(String),
});
const canSaveAll = await hasPermissionAsync(userId, 'save-all-canned-responses');
if (!canSaveAll && ['global'].includes(responseData.scope)) {
throw new Meteor.Error('error-not-allowed', 'Not allowed to modify canned responses on *global* scope', {
method: 'saveCannedResponse',
});
}View on GitHub (pinned to b2c16d5842)