{"record":{"id":"36739c10dc4b05ec","repo":"RocketChat/Rocket.Chat","slug":"error-pinning-message","errorCode":"error-pinning-message","errorMessage":"Error pinning message","messagePattern":"Error pinning message","errorType":"exception","errorClass":"PinMessagesNotAllowed","httpStatus":null,"severity":"error","filePath":"apps/meteor/client/lib/mutationEffects/updatePinMessage.ts","lineNumber":10,"sourceCode":"import type { IMessage } from '@rocket.chat/core-typings';\n\nimport { Messages } from '../../stores';\nimport { PinMessagesNotAllowed } from '../errors/PinMessagesNotAllowed';\n\nexport const updatePinMessage = (message: IMessage, data: Partial<IMessage>) => {\n\tconst msg = Messages.state.get(message._id);\n\n\tif (!msg) {\n\t\tthrow new PinMessagesNotAllowed('Error pinning message', {\n\t\t\tmethod: 'pinMessage',\n\t\t});\n\t}\n\n\tMessages.state.update(\n\t\t(record) => record._id === message._id && record.rid === message.rid,\n\t\t(record) => ({ ...record, ...data }),\n\t);\n};\n","sourceCodeStart":1,"sourceCodeEnd":20,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/client/lib/mutationEffects/updatePinMessage.ts#L1-L20","documentation":"Thrown as a PinMessagesNotAllowed (a RocketChatError subclass with code 'error-pinning-message') by updatePinMessage when the target message is not found in the local Messages store (Messages.state.get returns undefined). The function needs the cached message record to apply the pin/unpin update to the local store optimistically before the server confirms.","triggerScenarios":"The message being pinned/unpinned is not in the client's Messages cache. The message was deleted between the UI rendering the pin button and the user clicking it. The message ID is stale or incorrect. Store was reset (e.g., after logout/login) but the UI component retained old message references.","commonSituations":"User clicks pin on a message that was concurrently deleted. Message was evicted from cache in a very long room. Stale component state after room switch. Optimistic UI update fires before cache is populated.","solutions":["Verify the message exists in the Messages store before showing the pin/unpin control.","Catch the PinMessagesNotAllowed error and refresh the room's message history, then let the user retry.","Re-fetch the message into the store before calling updatePinMessage if it was evicted.","Disable the pin button for messages not present in the local cache."],"exampleFix":"// before\nupdatePinMessage(message, { pinned: true });\n// after\nif (!Messages.state.get(message._id)) {\n  await storeMessage(message);\n}\nupdatePinMessage(message, { pinned: true });","handlingStrategy":"validation","validationCode":"if (!Messages.state.get(message._id)) {\n  // message not in cache, store it first or skip pin\n  await storeMessage(message);\n}\nupdatePinMessage(message, data);","typeGuard":"const isMessageInStore = (messageId: string): boolean =>\n  Boolean(Messages.state.get(messageId));","tryCatchPattern":"try {\n  updatePinMessage(message, { pinned: true });\n} catch (e) {\n  if (e instanceof PinMessagesNotAllowed) {\n    dispatchToastMessage({ type: 'error', message: t('error-pinning-message') });\n    return;\n  }\n  throw e;\n}","preventionTips":["Check Messages.state.get(message._id) before calling updatePinMessage.","Catch PinMessagesNotAllowed specifically (it is a typed error with code 'error-pinning-message').","Refresh the message store if the message was evicted from cache in long rooms."],"tags":["pin-message","cache","client-store","rocket-chat-error","permissions"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}