RocketChat/Rocket.Chat · error · Meteor.Error

error-not-allowed

error-not-allowed

Error message

Not allowed

What it means

dmDeleteAction calls canAccessRoomIdAsync(room._id, userId) OR hasPermissionAsync(user, 'view-room-administration'). If both are false it throws error-not-allowed. Erasing a DM is therefore restricted to actual participants or workspace administrators with the view-room-administration permission.

Source

Thrown at apps/meteor/server/api/v1/im.ts:178

					type: 'boolean',
					enum: [true],
				},
			},
			required: ['success'],
			additionalProperties: false,
		}),
	},
};

const dmDeleteAction = <Path extends string>(_path: Path): TypedAction<typeof dmDeleteEndpointsProps, Path> =>
	async function action() {
		const { room } = await findDirectMessageRoom(this.bodyParams, this.userId);

		const canAccess =
			(await canAccessRoomIdAsync(room._id, this.userId)) || (await hasPermissionAsync(this.user, 'view-room-administration'));

		if (!canAccess) {
			throw new Meteor.Error('error-not-allowed', 'Not allowed');
		}

		await eraseRoom(room._id, this.user);

		return API.v1.success();
	};

const dmCloseAction = <Path extends string>(_path: Path): TypedAction<typeof dmCloseEndpointsProps, Path> =>
	async function action() {
		const { roomId } = this.bodyParams;
		if (!roomId) {
			throw new Meteor.Error('error-room-param-not-provided', 'Body param "roomId" is required');
		}
		if (!this.userId) {
			throw new Meteor.Error('error-invalid-user', 'Invalid user', {
				method: 'dm.close',
			});
		}

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Call the endpoint as one of the two DM participants.
  2. Grant the calling role/token owner the 'view-room-administration' permission if administrative deletion is intended.
  3. Use an admin token (admin role) for cleanup automation.
  4. Verify the target roomId actually belongs to a DM the caller is in (im.list).

Example fix

// before: bot token with no admin rights
await POST /api/v1/im.delete { roomId } // -> error-not-allowed

// after: grant permission or use participant token
await POST /api/v1/im.delete { roomId } // called by a DM participant, or by a role with view-room-administration
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check access without mutating
const me = await api.get('/api/v1/me');
const subs = await api.get('/api/v1/im.list');
const isParticipant = subs.data.ims.some(im => im._id === roomId);
const isAdmin = me.data.roles?.includes('admin');
if (!isParticipant && !isAdmin) throw new Error('Caller cannot delete this DM');

Try / catch

try {
  await api.post('/api/v1/im.delete', { roomId });
} catch (e) {
  if (e.response?.data?.error === 'error-not-allowed') {
    // switch to a participant/admin token, or skip
  } else throw e;
}

Prevention

When it happens

Trigger: POST /api/v1/im.delete by a user who is neither a member of the target DM nor holds the 'view-room-administration' permission. Authenticated but unauthorized deletion attempt.

Common situations: A bot or integration trying to clean up DMs it did not create; a normal user attempting to delete another user's DM; permission 'view-room-administration' was revoked from the calling role.

Related errors


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