RocketChat/Rocket.Chat · error · Error
message-not-found
Error message
message-not-found
What it means
Thrown by getPermaLink after it fails to find the message in both the local Messages store AND via a server REST API call to /v1/chat.getMessage. The function first checks the client cache (Messages.state.get), and if missing, calls getMessage which hits the API. If both return null/falsy, the message truly does not exist or the user lacks permission to read it.
Source
Thrown at apps/meteor/client/lib/getPermaLink.ts:24
try {
const { sdk } = await import('../../app/utils/client/lib/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 f9d3ec372b)
Solutions
- Catch the 'message-not-found' error in the caller and show a user-facing message like 'This message is no longer available'.
- Verify the message exists in the local cache before calling getPermaLink for messages the user is currently viewing.
- Check the user has access to the room containing the message before generating a permalink.
- Note that getMessage's internal catch block silently returns null on network errors — retry getPermaLink on transient failures.
Example fix
// before
try {
const link = await getPermaLink(msgId);
} catch (e) { /* unhandled */ }
// after
try {
const link = await getPermaLink(msgId);
} catch (e) {
if (e instanceof Error && e.message === 'message-not-found') {
dispatchToastMessage({ type: 'error', message: t('Message_not_available') });
return;
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
const msg = Messages.state.get(msgId);
if (!msg) {
// optionally try API, or show 'not available'
return;
}
const link = await getPermaLink(msgId); Type guard
const messageExistsInCache = (msgId: string): boolean => Boolean(Messages.state.get(msgId));
Try / catch
try {
const link = await getPermaLink(msgId);
} catch (e) {
if (e instanceof Error && e.message === 'message-not-found') {
dispatchToastMessage({ type: 'error', message: t('Message_not_available') });
return;
}
throw e;
} Prevention
- Check the Messages store before calling getPermaLink for locally available messages.
- Catch 'message-not-found' explicitly in permalink-generating code paths.
- Be aware that getMessage's internal catch block swallows network errors, returning null — retry on transient failures.
When it happens
Trigger: The message ID refers to a message that was deleted. The message exists but the user does not have read permission in the room. The message ID is valid but belongs to a room the user cannot access. Network error during the REST call causes getMessage to return null (it swallows errors in its catch block). Server is temporarily unreachable.
Common situations: Copying a link to a message that was deleted between page load and link generation. Message belongs to a private channel the user was removed from. Stale message ID from a bookmark or external link. Transient network failure during the API fallback.
Related errors
- room-not-found
- error-pinning-message
- Message not found
- Invalid main message
- The setting "${id}" is not readable.
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/8096da246c9dd1e8.
Report an issue: GitHub.