RocketChat/Rocket.Chat · error · Error
Param " " must be an object if provided
Error message
Param "${params.customFields.key}" must be an object if provided What it means
Validation error from POST channels.create: customFields was supplied but is not a plain object (map of field name to value). The API stores arbitrary custom fields keyed by name, so anything not typeof 'object' — a JSON string, array, or scalar — is rejected. Note this check does not validate against the custom fields configured in admin settings; that happens later in the create pipeline.
Solutions
- Send customFields as a plain JSON object: {"field":"value"}
- JSON.parse once if the value arrives as a string before putting it in the body
- Declare allowed custom fields in Administration > Settings > Rooms, otherwise they are dropped even when the shape is valid
Example fix
// before
{ "name": "dev-talk", "customFields": "{\"dept\":\"sales\"}" }
// after
{ "name": "dev-talk", "customFields": { "dept": "sales" } } Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof body.customFields === 'string') {
body.customFields = JSON.parse(body.customFields); // fix double-encoded JSON
}
if (body.customFields !== undefined && typeof body.customFields !== 'object') {
throw new Error('customFields must be an object');
} Type guard
const isCustomFieldsObject = (c: unknown): c is Record<string, unknown> => typeof c === 'object' && c !== null && !Array.isArray(c);
Try / catch
try { await POST('/api/v1/channels.create', body); } catch (e) {
if (/customFields.*must be an object/.test(e.message)) { /* send plain object */ }
} Prevention
- Never JSON.stringify the customFields value separately from the body
- Declare the custom field in admin settings or it will be stripped downstream
When it happens
Trigger: POST /api/v1/channels.create with customFields: "{\"dept\":\"sales\"}" (double-encoded JSON string) or customFields: ["dept"] instead of customFields: {"dept":"sales"}.
Common situations: Double-serialized JSON when a client stringifies the body twice; passing an array of key/value pairs from a form; forgetting to define the custom field in Administration > Rooms (custom fields must also be declared there or they are stripped later).
Related errors
- Param " " must be an array if provided
- Param " " is required
- Param must be an array
- error-not-allowed
- error-room-archived
AI-assisted analysis of RocketChat/Rocket.Chat@e4b8178b20 (2026-08-18).
Data as JSON: /api/errors/08500d6c95417632.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/server/api/v1/channels.ts:1027
const team = teamId && (await Team.getInfoById(teamId));
if (
(!teamId && !(await hasPermissionAsync(params.user.value, 'create-c'))) ||
(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 }> {View on GitHub (pinned to e4b8178b20)