n8n-io/n8n · error · ForbiddenError

Project roles are managed automatically and cannot be change

Error message

Project roles are managed automatically and cannot be changed manually

What it means

When project roles are provisioned automatically by an external system (SSO/SCIM role mapping), n8n locks down all manual membership mutations. assertProjectRolesNotManaged() throws 403 ForbiddenError if provisioningService.isProjectRoleManaged() returns true.

Source

Thrown at packages/cli/src/controllers/project.controller.ts:282

		_res: Response,
		@Body payload: UpdateProjectDto,
		@Param('projectId') projectId: string,
	) {
		await this.projectsService.updateProject(projectId, payload);
		this.eventService.emit('team-project-updated', {
			userId: req.user.id,
			role: req.user.role.slug,
			projectId,
			...(payload.customTelemetryTags !== undefined
				? { otelProjectCustomTagsCount: payload.customTelemetryTags.length }
				: {}),
		});
	}

	/** Throws when project roles are provisioned automatically, so manual membership changes are disallowed. */
	private async assertProjectRolesNotManaged() {
		if (await this.provisioningService.isProjectRoleManaged()) {
			throw new ForbiddenError(
				'Project roles are managed automatically and cannot be changed manually',
			);
		}
	}

	@Post('/:projectId/users')
	@ProjectScope('project:update')
	async addProjectUsers(
		req: AuthenticatedRequest,
		res: Response,
		@Param('projectId') projectId: string,
		@Body payload: AddUsersToProjectDto,
	) {
		await this.assertProjectRolesNotManaged();
		try {
			const { added, conflicts, project } =
				await this.projectsService.addUsersWithConflictSemantics(projectId, payload.relations);

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Manage project membership through the SSO/SCIM provider's role/group mappings instead of the API.
  2. If manual control is genuinely required, disable managed-roles mode (and understand the implications) via the provisioning/SSO configuration.
Defensive patterns

Strategy: try-catch

Validate before calling

// If a metadata endpoint exposes managed-roles mode, check it before attempting mutations.
async function isManaged(getProvisioningState) {
  return Boolean((await getProvisioningState())?.projectRoleManaged);
}

Try / catch

try {
  await api.post(`/projects/${projectId}/users`, payload);
} catch (e) {
  if (e.status === 403 && /managed automatically/.test(e.message)) {
    // instruct admin to use the SSO/SCIM provider for membership changes
  } else { throw e; }
}

Prevention

When it happens

Trigger: Any controller action guarded by assertProjectRolesNotManaged() — adding, changing, or deleting project users — invoked while provisioning reports that roles are externally managed.

Common situations: Enterprise SSO/SCIM with role mapping enabled; an admin attempts to add or reassign a project member through the UI or REST API while managed-roles mode is on.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/5638e4d5d0502b74. Report an issue: GitHub.