RocketChat/Rocket.Chat · error · Error

message-not-found

Error message

message-not-found

What it means

getPermaLink() throws 'message-not-found' when the message is neither in the local Messages store (Messages.state.get(msgId)) nor fetchable via GET /v1/chat.getMessage (getMessage() swallows errors and returns null). It means the permalink target genuinely cannot be resolved by this client.

Solutions

  1. Verify the message id exists and the user has read access to its room.
  2. Handle the throw and surface a 'message not available' state instead of a broken link.
  3. If the message should exist, retry once the network/permissions settle.

Example fix

// before
const url = await getPermaLink(msgId);

// after
try {
  const url = await getPermaLink(msgId);
} catch (e) {
  if (e instanceof Error && e.message === 'message-not-found') {
    dispatchToastMessage({ type: 'error', message: 'Message no longer available' });
    return;
  }
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!Messages.state.get(msgId)) {
  try {
    await sdk.rest.get('/v1/chat.getMessage', { msgId });
  } catch {
    return; // gone or inaccessible — skip permalink generation
  }
}
const url = await getPermaLink(msgId);

Try / catch

try {
  const url = await getPermaLink(msgId);
} catch (e) {
  if (e instanceof Error && e.message === 'message-not-found') {
    dispatchToastMessage({ type: 'error', message: 'Message no longer available' });
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Building a permalink for a deleted message, a message in a room the user cannot read, or an id that does not exist on this server; also when the REST call fails (network, permission) — the catch converts that to the same throw.

Common situations: Copy-link on a message removed moments earlier; permalinks shared across workspaces; API token without read access to the target room; offline moment during the fallback fetch.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@2f18297792 (2026-08-18). Data as JSON: /api/errors/8096da246c9dd1e8. Report an issue: GitHub.

Appendix: source

Thrown at apps/meteor/client/lib/getPermaLink.ts:24

	try {
		const { sdk } = await import('./SDKClient');
		const { message } = await sdk.rest.get('/v1/chat.getMessage', { msgId });
		return message;
	} catch {
		return null;
	}
};

export const getPermaLink = async (msgId: string): Promise<string> => {
	if (!msgId) {
		throw new Error('invalid-parameter');
	}

	const { Messages, Rooms, Subscriptions } = await import('../stores');

	const msg = Messages.state.get(msgId) || (await getMessage(msgId));
	if (!msg) {
		throw new Error('message-not-found');
	}
	const roomData = Rooms.state.get(msg.rid);

	if (!roomData) {
		throw new Error('room-not-found');
	}

	const subData = Subscriptions.state.find((record) => record.rid === roomData._id && record.u._id === getUserId());

	const { roomCoordinator } = await import('./rooms/roomCoordinator');

	const roomURL = roomCoordinator.getURL(roomData.t, { ...(subData || roomData), tab: '' });
	return `${roomURL}?msg=${msgId}`;
};

View on GitHub (pinned to 2f18297792)