RocketChat/Rocket.Chat · error · Meteor.Error

error-not-authorized

error-not-authorized

Error message

Not authorized

What it means

Thrown when Upload.canDeleteFile(user, file, null) resolves false — the authenticated user is not allowed to delete this upload. With msg=null the service (apps/meteor/server/services/upload/service.ts:60) allows deletion only if: the file has both userId and rid, AND either it is an unconfirmed upload (expiresAt set) owned by the caller with room access, OR the caller passes canDeleteMessageAsync against a synthetic message built from the file's owner/timestamp/room — i.e. ownership or room-level delete-message permission is required.

Source

Thrown at apps/meteor/server/meteor-methods/messages/deleteFileMessage.ts:51

			return deleteMessageValidatingPermission(msg, userId);
		}

		const user = await Users.findOneById(userId, { projection: { username: 1 } });
		if (!user) {
			throw new Meteor.Error('error-invalid-user', 'Invalid user', {
				method: 'deleteFileMessage',
			});
		}

		const file = await Uploads.findOneById(fileID, { projection: { userId: 1, rid: 1, expiresAt: 1, uploadedAt: 1 } });
		if (!file) {
			throw new Meteor.Error('error-invalid-file', 'Invalid file', {
				method: 'deleteFileMessage',
			});
		}

		if (!(await Upload.canDeleteFile(user, file, null))) {
			throw new Meteor.Error('error-not-authorized', 'Not authorized', {
				method: 'deleteFileMessage',
			});
		}

		return FileUpload.getStore('Uploads').deleteById(fileID);
	},
});

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Only offer deletion when the caller owns the file (file.userId === Meteor.userId()) or holds delete-message rights in that room
  2. Grant or obtain the required room permission (e.g. moderator role with delete-message capability) and retry
  3. Have the file owner or a room admin perform the deletion
  4. Fix Uploads records that lack userId/rid — they can never be deleted through this path

Example fix

// before
Meteor.call('deleteFileMessage', file._id); // shown for everyone's files

// after
const canDelete = file.userId === Meteor.userId() || subscription?.roles?.includes('moderator');
if (canDelete) {
  Meteor.call('deleteFileMessage', file._id);
}
Defensive patterns

Strategy: validation

Validate before calling

const uid = Meteor.userId();
const canDelete = file.userId === uid
  || Boolean(subscription?.roles?.includes('moderator'))
  || Boolean(subscription?.roles?.includes('owner'));
if (!canDelete) {
  // do not show/enable the delete action at all
}
Meteor.call('deleteFileMessage', file._id);

Try / catch

try {
  await Meteor.callAsync('deleteFileMessage', fileID);
} catch (e) {
  if ((e as Meteor.Error).error === 'error-not-authorized') {
    // inform the user they cannot delete this file; disable the action
  }
}

Prevention

When it happens

Trigger: A non-owner calls deleteFileMessage for another user's confirmed upload without moderator delete permissions; the caller lacks room access for file.rid; the upload's userId/rid fields are missing entirely (canDeleteFile returns false for incomplete records).

Common situations: UI shows a delete affordance based on stale or incomplete data; shared channels where users assume they can remove others' files; permission roles changed after the UI rendered; orphaned uploads missing userId/rid.

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/a7367cd5682583f4. Report an issue: GitHub.