{"record":{"id":"bceef549c9650d39","repo":"RocketChat/Rocket.Chat","slug":"error-action-not-allowed-bceef5","errorCode":"error-action-not-allowed","errorMessage":"error-action-not-allowed","messagePattern":"error-action-not-allowed","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/omnichannel/messages.ts","lineNumber":112,"sourceCode":"\t\tvoid callbacks.run('livechat.offlineMessage', data);\n\t});\n}\n\nexport async function updateMessage({ guest, message }: { guest: ILivechatVisitor; message: AtLeast<IMessage, '_id' | 'msg' | 'rid'> }) {\n\t// TODO: Remove check\n\tcheck(message, Match.ObjectIncluding({ _id: String }));\n\n\tconst originalMessage = await Messages.findOneById<Pick<IMessage, 'u' | '_id'>>(message._id, { projection: { u: 1 } });\n\tif (!originalMessage?._id) {\n\t\treturn;\n\t}\n\n\t// TODO: shouldn't this happen inside updateMessageFunc?\n\tconst editAllowed = settings.get('Message_AllowEditing');\n\tconst editOwn = originalMessage.u && originalMessage.u._id === guest._id;\n\n\tif (!editAllowed || !editOwn) {\n\t\tthrow new Error('error-action-not-allowed');\n\t}\n\n\t// TODO: Apps sends an `any` object and apparently we just check for _id being present\n\t// while updateMessage expects AtLeast<id, msg, rid>\n\tawait updateMessageFunc(message, guest as unknown as IUser);\n\n\treturn true;\n}\n\nexport async function deleteMessage({ guest, message }: { guest: ILivechatVisitor; message: IMessage }) {\n\tconst deleteAllowed = settings.get<boolean>('Message_AllowDeleting');\n\tconst editOwn = message.u && message.u._id === guest._id;\n\n\tif (!deleteAllowed || !editOwn) {\n\t\tthrow new Error('error-action-not-allowed');\n\t}\n\n\t// TODO: we shouldn't do this :(","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/omnichannel/messages.ts#L94-L130","documentation":"Thrown by the guest message-edit flow (guests.ts) when `Message_AllowEditing` is false OR the original message's owner (`originalMessage.u._id`) is not the guest making the request. Guests may only edit their own messages and only while global message editing is enabled; either condition failing aborts before `updateMessageFunc` runs.","triggerScenarios":"A livechat visitor widget calling the edit-message API after an admin disabled 'Message_AllowEditing'; or an integration editing a message on behalf of a guest who did not send it (mismatched guest._id vs message.u._id).","commonSituations":"Workspace policy turns off message editing and the widget's edit button was not hidden; messages edited after agent takeover where ownership metadata changed; tests replaying guest traffic with synthetic ids.","solutions":["Enable the `Message_AllowEditing` setting if guests should edit","Hide/disable the edit action in the widget when editing is not allowed or the message is not the guest's own","Ensure the edit call authenticates as the same guest who authored the message"],"exampleFix":"// before\nawait updateMessage({ guest, message: { _id: msgId, msg: 'new text' } });\n\n// after\nconst original = await Messages.findOneById(msgId, { projection: { u: 1 } });\nif (!settings.get('Message_AllowEditing') || original?.u?._id !== guest._id) {\n  throw new Error('Editing this message is not allowed');\n}\nawait updateMessage({ guest, message: { _id: msgId, msg: 'new text' } });","handlingStrategy":"validation","validationCode":"const original = await Messages.findOneById<Pick<IMessage, 'u'>>(message._id, { projection: { u: 1 } });\nif (!settings.get('Message_AllowEditing') || original?.u?._id !== guest._id) {\n  throw new Error('Editing is not allowed for this message');\n}\nawait updateMessage({ guest, message });","typeGuard":"const guestOwnsMessage = (guest: { _id: string }, msg: { u?: { _id?: string } }): boolean =>\n  msg.u?._id === guest._id;","tryCatchPattern":"try {\n  await updateMessage({ guest, message });\n} catch (e) {\n  if (e instanceof Error && e.message === 'error-action-not-allowed') {\n    // hide edit affordance; editing disabled or message not the guest's own\n  }\n}","preventionTips":["Gate the widget's edit UI on Message_AllowEditing from livechat config","Only offer edit on messages authored by the current guest","Re-check permissions when workspace settings change at runtime"],"tags":["omnichannel","messages","editing","permissions","livechat"],"backgroundTag":"permission-denied","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}