calcom/cal.diy · error · NotFoundException

User with ID ${userId} is not part of this OAuth client.

Error message

User with ID ${userId} is not part of this OAuth client.

What it means

Thrown by OAuthClientUsersController.validateManagedUserOwnership when userRepository.findByIdWithinPlatformScope(userId, clientId) returns falsy. The helper restricts the lookup to the given OAuth client's platform scope, so it fails both when the user does not exist and when the user exists but was not created under that OAuth client. Raised as NotFoundException (HTTP 404) per the message.

Source

Thrown at apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.ts:213

    const { accessToken, refreshToken, accessTokenExpiresAt, refreshTokenExpiresAt } =
      await this.tokensRepository.forceRefreshOAuthTokens(oAuthClientId, id);

    return {
      status: SUCCESS_STATUS,
      data: {
        accessToken,
        refreshToken,
        accessTokenExpiresAt: accessTokenExpiresAt.valueOf(),
        refreshTokenExpiresAt: refreshTokenExpiresAt.valueOf(),
      },
    };
  }

  private async validateManagedUserOwnership(clientId: string, userId: number): Promise<User> {
    const user = await this.userRepository.findByIdWithinPlatformScope(userId, clientId);
    if (!user) {
      throw new NotFoundException(`User with ID ${userId} is not part of this OAuth client.`);
    }

    return user;
  }
}

View on GitHub (pinned to 176037d0af)

Solutions

  1. List managed users for the clientId (GET endpoint) and use an id that is actually scoped to that client.
  2. Confirm clientId and userId come from the same OAuth client context (do not mix ids across clients).
  3. If the managed user was deleted, inform the caller and re-create or pick an existing one.
Defensive patterns

Strategy: validation

Validate before calling

const user = await userRepository.findByIdWithinPlatformScope(userId, clientId);
if (!user) {
  throw new NotFoundException(`User with ID ${userId} is not part of this OAuth client.`);
}

Prevention

When it happens

Trigger: An operation on a managed user (e.g. token refresh, update, delete) passes a userId that is not a managed user of the supplied clientId. The scoped repository query returns nothing and the guard throws before proceeding.

Common situations: Cross-client access: using a userId from OAuth client A against client B; userId from a stale list after the managed user was removed; clientId/userId parameter swap in the caller; the managed user was migrated or reassigned.

Related errors


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