RocketChat/Rocket.Chat · error · Meteor.Error
error-not-authorized
error-not-authorized
Error message
Not authorized
What it means
Permission gate in /unarchiveroom: after the room type allows the ARCHIVE action, hasPermissionAsync(userId, 'unarchive-room', room._id) is evaluated (role permission, optionally scoped to the room). If the user lacks the 'unarchive-room' permission the command throws 'error-not-authorized'. Unlike the earlier user-facing branches (which send ephemeral messages), this and the room-type check are hard errors.
Source
Thrown at apps/meteor/server/slashcommands/unarchiveroom/server.ts:55
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'archiveRoom' });
}
if (!room) {
void api.broadcast('notify.ephemeralMessage', userId, message.rid, {
msg: i18n.t('Channel_doesnt_exist', {
channelName: channel,
lng: settings.get('Language') || 'en',
}),
});
return;
}
if (!(await roomCoordinator.getRoomDirectives(room.t).allowMemberAction(room, RoomMemberActions.ARCHIVE, userId))) {
throw new Meteor.Error('error-room-type-not-unarchivable', `Room type: ${room.t} can not be unarchived`);
}
if (!(await hasPermissionAsync(userId, 'unarchive-room', room._id))) {
throw new Meteor.Error('error-not-authorized', 'Not authorized');
}
if (!room.archived) {
void api.broadcast('notify.ephemeralMessage', userId, message.rid, {
msg: i18n.t('Channel_already_Unarchived', {
channelName: channel,
lng: settings.get('Language') || 'en',
}),
});
return;
}
await unarchiveRoom(room._id, user);
void api.broadcast('notify.ephemeralMessage', userId, message.rid, {
msg: i18n.t('Channel_Unarchived', {
channelName: channel,
lng: settings.get('Language') || 'en',View on GitHub (pinned to b2c16d5842)
Solutions
- Grant the user (or their role) the 'unarchive-room' permission in Administration > Permissions, globally or scoped to the room/channel.
- Have an admin or moderator with the permission perform the unarchive.
- Before sending the command, check hasPermission('unarchive-room', roomId) client-side and hide/disable the action.
Example fix
// before
if (!(await hasPermissionAsync(userId, 'unarchive-room', room._id))) {
throw new Meteor.Error('error-not-authorized', 'Not authorized');
}
// client-side pre-check to avoid the error
const canUnarchive = useHasPermission('unarchive-room', rid);
// render the /unarchive entry point only when canUnarchive is true Defensive patterns
Strategy: validation
Validate before calling
// Client-side, before enabling the action
const canUnarchive = useHasPermission('unarchive-room', rid);
if (!canUnarchive) { /* hide/disable the unarchive control */ } Try / catch
try { await Meteor.callAsync('slashCommand', { command: 'unarchiveroom', ... }); } catch (e) { if (isMeteorError(e, 'error-not-authorized')) { /* request unarchive-room permission or escalate to admin */ return; } throw e; } Prevention
- Grant 'unarchive-room' to the roles that need it, scoped per room where possible.
- Check permission before sending the command.
- Route unarchive requests through admins when role permissions are locked down.
When it happens
Trigger: A regular member or non-admin user runs /unarchive #channel without holding a role that includes 'unarchive-room' for that room (global or room-scoped).
Common situations: Default role setups where only admin/moderator has unarchive-room; users with room-scoped roles that grant archive but not unarchive; permission removed by an admin policy change.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/0f925c52a83eb31c.
Report an issue: GitHub.