RocketChat/Rocket.Chat · warning · Error

Param ${params.teams.key} must be an array

Error message

Param ${params.teams.key} must be an array

What it means

Thrown during channel creation when params.teams.value is present but not an array. Unlike the members message, this one omits the 'if provided' phrasing and uses inconsistent quoting (no surrounding quotes around the key) - a minor message inconsistency. The param key is interpolated.

Source

Thrown at apps/meteor/server/api/v1/channels.ts:1030

		(teamId && team && !(await hasPermissionAsync(params.user.value, 'create-team-channel', team.roomId)))
	) {
		throw new Error('unauthorized');
	}

	if (!params.name?.value) {
		throw new Error(`Param "${params.name?.key}" is required`);
	}

	if (params.members?.value && !Array.isArray(params.members.value)) {
		throw new Error(`Param "${params.members.key}" must be an array if provided`);
	}

	if (params.customFields?.value && !(typeof params.customFields.value === 'object')) {
		throw new Error(`Param "${params.customFields.key}" must be an object if provided`);
	}

	if (params.teams?.value && !Array.isArray(params.teams.value)) {
		throw new Error(`Param ${params.teams.key} must be an array`);
	}
}

async function createChannel(
	userId: string,
	params: {
		name?: string;
		members?: string[];
		customFields?: Record<string, any>;
		extraData?: Record<string, any>;
		readOnly?: boolean;
		excludeSelf?: boolean;
	},
): Promise<{ channel: IRoom }> {
	const readOnly = typeof params.readOnly !== 'undefined' ? params.readOnly : false;
	const id = await createChannelMethod(
		userId,
		params.name || '',

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Send teams as a JSON array, even for a single team: teams: ['teamId123'].
  2. Validate the teams param shape client-side before submission.
  3. Normalize the message to match the members style (quote the key) if you own the code.

Example fix

// before - request body
{ "name": "room", "teams": "generalTeam" }

// after
{ "name": "room", "teams": ["generalTeam"] }
Defensive patterns

Strategy: validation

Validate before calling

function normalizeTeams(teams) {
  if (teams == null) return undefined;
  if (typeof teams === 'string') return [teams];
  if (Array.isArray(teams)) return teams;
  throw new Error('teams must be an array');
}

Type guard

function isStringArray(value) {
  return Array.isArray(value) && value.every(v => typeof v === 'string');
}

Try / catch

try {
  await api.createChannel({ name, teams });
} catch (e) {
  if (/must be an array/.test(e.message)) {
    teams = Array.isArray(teams) ? teams : [teams];
    return api.createChannel({ name, teams });
  }
  throw e;
}

Prevention

When it happens

Trigger: Submitting teams as a single team ID string or an object instead of an array of team identifiers.

Common situations: Client sending teams: 'teamId123' instead of teams: ['teamId123']; migration script reusing a scalar team field for the new array param.

Related errors


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