RocketChat/Rocket.Chat · error · Error
unauthorized
Error message
unauthorized
What it means
Plain Error thrown by validateChannelParams (the shared validator for POST channels.create) when the calling user lacks permission to create channels: without a teamId you need the 'create-c' permission; with a valid teamId you need 'create-team-channel' on that team's room. Note the quirk that an unknown teamId (team lookup fails) skips the permission check rather than erroring here.
Solutions
- Grant the user's role the create-c permission (or create-team-channel for team channels) in Administration > Permissions
- Verify the authenticated user with GET /api/v1/me and check its roles before calling create
- For team channels, confirm the user is a member of the target team and the role has create-team-channel on that team room
Defensive patterns
Strategy: validation
Validate before calling
const me = await GET('/api/v1/me');
const canCreate = me.roles.includes('admin') || (await GET('/api/v1/permissions', { userId: me._id }))
.update.some((p) => p._id === 'create-c'); Try / catch
try { await POST('/api/v1/channels.create', body); } catch (e) {
if (e.message === 'unauthorized') { /* request create-c permission grant */ }
} Prevention
- Provision bot/API roles with create-c explicitly in setup scripts
- Check permissions endpoints before shipping self-service channel creation UI
When it happens
Trigger: POST /api/v1/channels.create by a user whose role lacks create-c; or with teamId supplied and a valid team where the user lacks create-team-channel; commonly a bot/CI token whose role was never granted channel-creation permissions.
Common situations: Newly created API users or bots with minimal roles; self-service guest roles that cannot create channels; attempting to create a channel inside a team the user only joined as a guest; custom role permission resets after an upgrade.
Understand the failure class
Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- error-not-allowed
- error-invalid-role
- error-permission-not-found
- error-action-not-allowed
- error-action-not-allowed
AI-assisted analysis of RocketChat/Rocket.Chat@e4b8178b20 (2026-08-18).
Data as JSON: /api/errors/fe50b87e122da6c9.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/server/api/v1/channels.ts:1015
},
);
async function createChannelValidator(params: {
user: { value: string };
name?: { key: string; value?: string };
members?: { key: string; value?: string[] };
customFields?: { key: string; value?: string };
teams?: { key: string; value?: string[] };
teamId?: { key: string; value?: string };
}) {
const teamId = params.teamId?.value;
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`);
}
}View on GitHub (pinned to e4b8178b20)