Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code ee30294af2 SendInvitations fails with EntityNotFoundError when workspace not fully activated
https://sonarly.com/issue/4106?type=bug

The `sendInvitations` resolver assumes a workspace member always exists, but the auth system deliberately bypasses workspace member checks during workspace creation states, creating a mismatch that crashes when users reach the invite-team step before activation fully completes.

Fix: ## Root Cause

The `sendInvitations` resolver crashes with `EntityNotFoundError` because `findOneOrFail` can find no workspace member when the workspace is stuck in `ONGOING_CREATION`. The workspace member record is only created during `activateWorkspace()`, but if that process fails mid-way the workspace is permanently stuck in `ONGOING_CREATION` with no rollback.

The auth layer correctly bypasses workspace member validation for both `PENDING_CREATION` and `ONGOING_CREATION` states (jwt.auth.strategy.ts:183-189), so the request passes all guards. However, `isWorkspaceActivationPending` in `onboarding.service.ts` only checked `PENDING_CREATION` — not `ONGOING_CREATION` — so the onboarding flow failed to redirect users back to the workspace activation step and instead routed them to `/invite-team`.

## Fix

Added `ONGOING_CREATION` to the `isWorkspaceActivationPending` check so that workspaces stuck in that state return `OnboardingStatus.WORKSPACE_ACTIVATION` instead of falling through to `INVITE_TEAM`:

```typescript file=packages/twenty-server/src/engine/core-modules/onboarding/onboarding.service.ts lines=37-43
private isWorkspaceActivationPending(workspace: WorkspaceEntity) {
  return (
    workspace.activationStatus ===
      WorkspaceActivationStatus.PENDING_CREATION ||
    workspace.activationStatus === WorkspaceActivationStatus.ONGOING_CREATION
  );
}
```

This ensures that when a workspace is in `ONGOING_CREATION` (activation in-progress or failed), the frontend routes the user back to the workspace activation step rather than to `/invite-team` where `findOneOrFail` will throw because no workspace member record has been created yet.
2026-03-05 11:01:38 +00:00
@@ -36,7 +36,9 @@ export class OnboardingService {
private isWorkspaceActivationPending(workspace: WorkspaceEntity) {
return (
workspace.activationStatus === WorkspaceActivationStatus.PENDING_CREATION
workspace.activationStatus ===
WorkspaceActivationStatus.PENDING_CREATION ||
workspace.activationStatus === WorkspaceActivationStatus.ONGOING_CREATION
);
}