RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-shortcut
error-invalid-shortcut
Error message
Shortcut provided already exists
What it means
Thrown by saveCannedResponse when a canned response with the same shortcut already exists and would collide. Collision is detected via CannedResponse.findOneByShortcut: it fires on a create with no _id where the shortcut exists, or on an update (_id set) where a different document owns the shortcut. Code is 'error-invalid-shortcut'.
Source
Thrown at apps/meteor/ee/server/meteor-methods/saveCannedResponse.ts:61
const canSaveDepartment = await hasPermissionAsync(userId, 'save-department-canned-responses');
if (!canSaveAll && !canSaveDepartment && ['department'].includes(responseData.scope)) {
throw new Meteor.Error('error-not-allowed', 'Not allowed to modify canned responses on *department* scope', {
method: 'saveCannedResponse',
});
}
// to avoid inconsistencies
if (responseData.scope === 'user') {
delete responseData.departmentId;
}
// TODO: check if the department i'm trying to save is a department i can interact with
// check if the response already exists and we're not updating one
const duplicateShortcut = await CannedResponse.findOneByShortcut(responseData.shortcut, {
projection: { _id: 1 },
});
if ((!_id && duplicateShortcut) || (_id && duplicateShortcut && duplicateShortcut._id !== _id)) {
throw new Meteor.Error('error-invalid-shortcut', 'Shortcut provided already exists', {
method: 'saveCannedResponse',
});
}
if (responseData.scope === 'department' && !responseData.departmentId) {
throw new Meteor.Error('error-invalid-department', 'Invalid department', {
method: 'saveCannedResponse',
});
}
if (
responseData.departmentId &&
!(await LivechatDepartment.findOneById<Pick<ILivechatDepartment, '_id'>>(responseData.departmentId, { projection: { _id: 1 } }))
) {
throw new Meteor.Error('error-invalid-department', 'Invalid department', {
method: 'saveCannedResponse',
});
}View on GitHub (pinned to f9d3ec372b)
Solutions
- Check shortcut uniqueness via CannedResponse.findOneByShortcut before submit and warn the user.
- Enforce unique shortcut input in the UI (debounced availability check).
- On collision, prompt the user to pick a different shortcut or update the existing response instead.
Example fix
// before
await saveCannedResponse(userId, responseData, _id);
// after
const dup = await CannedResponse.findOneByShortcut(responseData.shortcut, { projection: { _id: 1 } });
if (dup && dup._id !== _id) {
throw new Error('Shortcut already in use');
}
await saveCannedResponse(userId, responseData, _id); Defensive patterns
Strategy: validation
Validate before calling
const dup = await CannedResponse.findOneByShortcut(responseData.shortcut, { projection: { _id: 1 } });
if (dup && dup._id !== _id) {
throw new Error('Shortcut already in use');
}
await saveCannedResponse(userId, responseData, _id); Type guard
function isShortcutValid(shortcut: string): boolean {
return /^[a-z0-9-_]{1,32}$/i.test(shortcut);
} Try / catch
try {
await saveCannedResponse(userId, responseData, _id);
} catch (e) {
if (isMeteorError(e, 'error-invalid-shortcut')) {
notifyUser(`The shortcut "${responseData.shortcut}" is already taken.`);
return;
}
throw e;
} Prevention
- Run a debounced shortcut-availability check in the UI before submit.
- Validate shortcut format/length before uniqueness lookup.
- On collision, prompt to rename or update the existing response.
When it happens
Trigger: Creating a new canned response with a shortcut already in use; renaming an existing response to a shortcut owned by another response.
Common situations: User picks a shortcut like '/hi' that is already taken; import/seed data introduces duplicate shortcuts; UI does not check uniqueness inline before submit.
Related errors
- error-canned-response-not-found
- Invalid Api parameter provided, it must be a valid IApi obje
- Invalid command parameter provided, must be a string.
- Invalid Slash Command parameter provided, it must be a valid
- The environmental variable "${envVarName}" is not readable.
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/c9676ddb5a1e076e.
Report an issue: GitHub.