RocketChat/Rocket.Chat · error · Meteor.Error
error-canned-response-not-found
error-canned-response-not-found
Error message
Canned Response not found
What it means
saveCannedResponse (saveCannedResponse.ts:86) takes the update path when _id is provided; if CannedResponse.findOneById(_id) returns null (the record was deleted after the editor loaded it), it throws error-canned-response-not-found instead of upserting.
Solutions
- Refresh the canned responses list; if the record is gone, create it again instead of updating
- Handle error-canned-response-not-found in the editor by warning the user the item was deleted
- Pre-check existence before saving when the editing session is long-lived
Example fix
// before
await saveCannedResponse(uid, responseData, _id);
// after
const existing = _id ? await CannedResponse.findOneById(_id, { projection: { _id: 1 } }) : null;
if (_id && !existing) {
// record deleted meanwhile — fall back to create
return saveCannedResponse(uid, responseData);
}
await saveCannedResponse(uid, responseData, _id); Defensive patterns
Strategy: validation
Validate before calling
if (_id) {
const existing = await CannedResponse.findOneById(_id, { projection: { _id: 1 } });
if (!existing) {
// record deleted meanwhile — create instead of update
return saveCannedResponse(userId, responseData);
}
}
await saveCannedResponse(userId, responseData, _id); Try / catch
try {
await saveCannedResponse(userId, responseData, _id);
} catch (e) {
if (e instanceof Meteor.Error && e.error === 'error-canned-response-not-found') {
// refresh the list and re-open; the record was deleted by someone else
}
throw e;
} Prevention
- Re-check existence before saving long-lived editor forms
- Surface deletion notices to concurrent editors (canned-responses stream emits 'removed')
- Treat update-on-deleted as a create-or-abort decision, never a blind retry
When it happens
Trigger: Updating a canned response that no longer exists — another user/session deleted it while the editor form was open, or the _id is stale/wrong.
Common situations: Two agents editing the same canned response and one deleting it; list not refreshed after a deletion; retrying a save after the record was removed by an admin cleanup.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- error-canned-response-not-found
- department-not-found
- error-contact-not-found
- error-contact-not-found
- error-contact-not-found
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/343afb98ee142483.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/ee/server/meteor-methods/saveCannedResponse.ts:86
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',
});
}
let result: Omit<IOmnichannelCannedResponse, '_updatedAt' | '_createdAt'> & { _createdAt?: Date };
if (_id) {
const cannedResponse = await CannedResponse.findOneById(_id);
if (!cannedResponse) {
throw new Meteor.Error('error-canned-response-not-found', 'Canned Response not found', {
method: 'saveCannedResponse',
});
}
result = await CannedResponse.updateCannedResponse(_id, {
...responseData,
...(cannedResponse.scope === 'user' && { userId: cannedResponse.userId }),
createdBy: cannedResponse.createdBy,
});
} else {
const user = await Users.findOneById(userId);
const data = {
...responseData,
...(responseData.scope === 'user' && { userId: user?._id }),
createdBy: { _id: user?._id || '', username: user?.username || '' },
_createdAt: new Date(),
};View on GitHub (pinned to b2c16d5842)