RocketChat/Rocket.Chat · error · PinMessagesNotAllowed

error-pinning-message

error-pinning-message

Error message

Error pinning message

What it means

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.

Source

Thrown at apps/meteor/client/lib/mutationEffects/updatePinMessage.ts:10

import type { IMessage } from '@rocket.chat/core-typings';

import { Messages } from '../../stores';
import { PinMessagesNotAllowed } from '../errors/PinMessagesNotAllowed';

export const updatePinMessage = (message: IMessage, data: Partial<IMessage>) => {
	const msg = Messages.state.get(message._id);

	if (!msg) {
		throw new PinMessagesNotAllowed('Error pinning message', {
			method: 'pinMessage',
		});
	}

	Messages.state.update(
		(record) => record._id === message._id && record.rid === message.rid,
		(record) => ({ ...record, ...data }),
	);
};

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Verify the message exists in the Messages store before showing the pin/unpin control.
  2. Catch the PinMessagesNotAllowed error and refresh the room's message history, then let the user retry.
  3. Re-fetch the message into the store before calling updatePinMessage if it was evicted.
  4. Disable the pin button for messages not present in the local cache.

Example fix

// before
updatePinMessage(message, { pinned: true });
// after
if (!Messages.state.get(message._id)) {
  await storeMessage(message);
}
updatePinMessage(message, { pinned: true });
Defensive patterns

Strategy: validation

Validate before calling

if (!Messages.state.get(message._id)) {
  // message not in cache, store it first or skip pin
  await storeMessage(message);
}
updatePinMessage(message, data);

Type guard

const isMessageInStore = (messageId: string): boolean =>
  Boolean(Messages.state.get(messageId));

Try / catch

try {
  updatePinMessage(message, { pinned: true });
} catch (e) {
  if (e instanceof PinMessagesNotAllowed) {
    dispatchToastMessage({ type: 'error', message: t('error-pinning-message') });
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12). Data as JSON: /api/errors/36739c10dc4b05ec. Report an issue: GitHub.