RocketChat/Rocket.Chat · error · Meteor.Error

error-not-allowed

error-not-allowed

Error message

Not allowed

What it means

createChannel guard when teamId resolved to a real team: hasPermissionAsync(userId, 'create-team-channel', team.roomId) returned false. Creating a channel inside a team requires the create-team-channel permission scoped to that team's room - by default held by team owners/managers and admins, not ordinary members.

Source

Thrown at apps/meteor/server/meteor-methods/rooms/createChannel.ts:50

) => {
	check(name, String);
	check(members, Match.Optional([String]));
	if (!userId) {
		throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'createChannel' });
	}

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

	if (extraData.teamId) {
		const team = await Team.findOneById<Pick<ITeam, '_id' | 'roomId'>>(extraData.teamId, { projection: { roomId: 1 } });
		if (!team) {
			throw new Meteor.Error('error-team-not-found', 'The "teamId" param provided does not match any team', { method: 'createChannel' });
		}
		if (!(await hasPermissionAsync(userId, 'create-team-channel', team.roomId))) {
			throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'createChannel' });
		}
	} else if (!(await hasPermissionAsync(userId, 'create-c'))) {
		throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'createChannel' });
	}

	return createRoom('c', name, user, members, excludeSelf, readOnly, {
		...(customFields && Object.keys(customFields).length && { customFields }),
		...extraData,
	});
};

Meteor.methods<ServerMethods>({
	async createChannel(name, members, readOnly = false, customFields = {}, extraData = {}) {
		methodDeprecationLogger.method('createChannel', '9.0.0', '/v1/channels.create');
		const uid = Meteor.userId();

		if (!uid) {
			throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'createChannel' });

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Ask a team owner/manager or admin to create the channel, or grant create-team-channel to the member's role on that team.
  2. Create the channel without teamId and have an owner link it to the team afterwards.
  3. Run automation under an account that holds create-team-channel for the team.

Example fix

// before
Meteor.call('createChannel', name, members, false, {}, { teamId });

// after
if (isTeamOwnerOrAdmin(team, Meteor.userId())) {
  Meteor.call('createChannel', name, members, false, {}, { teamId });
} else {
  showToast('Ask a team owner to add this channel');
}
Defensive patterns

Strategy: try-catch

Validate before calling

// if the teams data exposes the caller's role, gate the UI on it:
if (!isTeamOwnerOrAdmin(teamInfo, Meteor.userId())) {
  // hide the add-channel-to-team action for this user
}

Try / catch

try {
  await Meteor.callAsync('createChannel', name, members, false, {}, { teamId });
} catch (e) {
  if (e instanceof Meteor.Error && e.error === 'error-not-allowed') {
    // lacks create-team-channel on this team - suggest asking an owner
    showToast('Only team owners/managers can add channels to this team');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: A plain team member calls createChannel with that team's teamId; the role lost create-team-channel on the team; workspace policy restricts team channel creation to owners.

Common situations: Members expecting to add channels to teams they joined; permission reshuffles after role refactors; automations creating team channels under a member account.

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