calcom/cal.diy · error · BadRequestException

You cannot create a managed user outside of an organization

Error message

You cannot create a managed user outside of an organization - the OAuth client does not belong to any organization.

What it means

Thrown by createOAuthClientUser when oAuthClient.organizationId is null/undefined. Managed users are organization-scoped by design; an OAuth client that is not bound to an organization cannot host managed users, so the create is rejected up front with BadRequestException (HTTP 400) before any user record is touched.

Source

Thrown at apps/api/v2/src/modules/oauth-clients/services/oauth-clients-users.service.ts:41

    private readonly schedulesService: SchedulesService_2024_04_15,
    private readonly calendarsService: CalendarsService,
    private readonly profilesRepository: ProfilesRepository
  ) {}

  async createOAuthClientUser(oAuthClient: PlatformOAuthClient, body: CreateManagedUserInput) {
    const oAuthClientId = oAuthClient.id;
    const organizationId = oAuthClient.organizationId;

    const existingUser = await this.getExistingUserByEmail(oAuthClientId, body.email);
    if (existingUser) {
      throw new ConflictException(
        `User with the provided e-mail already exists. Existing user ID=${existingUser.id}`
      );
    }

    let user: User;
    if (!organizationId) {
      throw new BadRequestException(
        "You cannot create a managed user outside of an organization - the OAuth client does not belong to any organization."
      );
    } else {
      const email = OAuthClientUsersService.getOAuthUserEmail(oAuthClientId, body.email);
      const createdUser = (
        await createNewUsersConnectToOrgIfExists({
          invitations: [
            {
              usernameOrEmail: email,
              role: "MEMBER",
            },
          ],
          creationSource: CreationSource.API_V2,
          teamId: organizationId,
          isOrg: true,
          parentId: null,
          autoAcceptEmailDomain: "never-auto-accept-email-domain-for-managed-users",
          orgConnectInfoByUsernameOrEmail: {

View on GitHub (pinned to 176037d0af)

Solutions

  1. Ensure the OAuth client is created under an organization so organizationId is set.
  2. Recreate or migrate the client so it is bound to the intended organization.
  3. Before provisioning, assert oAuthClient.organizationId is non-null.
  4. If org-less provisioning is genuinely required, reconsider — the API forbids it by design.

Example fix

// before
const client = await getOrglessClient();
await oauthClientUsersService.createOAuthClientUser(client, { email }); // 400

// after — bind the client to an org first
const client = await createOAuthClientInOrg(orgId, payload);
await oauthClientUsersService.createOAuthClientUser(client, { email });
Defensive patterns

Strategy: validation

Validate before calling

// Assert the client is org-bound before provisioning managed users
function assertClientHasOrg(client: { organizationId: number | null }) {
  if (!client.organizationId) {
    throw new Error('Cannot provision managed users: OAuth client has no organization');
  }
}
await assertClientHasOrg(oAuthClient);

Type guard

function isOrgBoundClient(client: unknown): client is { organizationId: number } {
  return typeof (client as any)?.organizationId === 'number' && (client as any).organizationId > 0;
}

Try / catch

// Validate up front; a missing org is a configuration defect, not a transient error.

Prevention

When it happens

Trigger: Calling managed-user creation with an OAuth client whose organizationId is null. This reflects a client created outside the org-owned flow (legacy or misconfigured client).

Common situations: A legacy OAuth client predating the org requirement; a client created via a path that didn't set organizationId; using a personal-level client for org-scoped managed-user provisioning.

Related errors


AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12). Data as JSON: /api/errors/4ce1e89c54a67af2. Report an issue: GitHub.