https://sonarly.com/issue/7805?type=bug
The `useCurrentPlan` hook throws "Current plan not found" when a workspace's Stripe subscription metadata lacks a `plan` key, crashing the entire billing settings page.
Fix: ## Classification: Category D — Data Integrity Issue
Legacy subscriptions created before the Sept 2025 billing refactoring (`43e0cd5d05`) have `metadata: {}` or `metadata: { workspaceId: '...' }` — no `plan` key. The server already handles this gracefully in `getPlanKeyFromSubscription` by defaulting to `BillingPlanKey.PRO`. The frontend hook was introduced in the same refactoring without this fallback.
## Fix
Extract the plan key resolution into a single variable with a `?? BillingPlanKey.PRO` fallback, matching server-side behavior. `findOrThrow` is preserved so it still throws for genuinely unknown plan key strings in metadata.
```typescript file=packages/twenty-front/src/modules/billing/hooks/useCurrentPlan.ts lines=14-28
const planKeyFromMetadata =
(currentWorkspace.currentBillingSubscription?.metadata?.['plan'] as
| BillingPlanKey
| undefined) ?? BillingPlanKey.PRO;
const currentPlan = findOrThrow(
listPlans(),
(plan) => plan.planKey === planKeyFromMetadata,
new Error('Current plan not found'),
);
const oppositPlan =
planKeyFromMetadata === BillingPlanKey.ENTERPRISE
? BillingPlanKey.PRO
: BillingPlanKey.ENTERPRISE;
```
**Why this is correct and not a banned pattern:** This is not silencing an error — it applies the same business rule that already exists server-side: a subscription without a `plan` metadata key is treated as `PRO`. The fallback is deliberate and mirrors the canonical server logic. `findOrThrow` still guards against a completely unrecognized plan key value in the metadata.
**Secondary benefit:** The original code read `metadata?.['plan']` twice (once in `findOrThrow`, once in the `oppositPlan` ternary), with both being independent raw accesses. Now both use the single resolved `planKeyFromMetadata`, making the logic consistent.
**Note for the team:** Consider a backfill script/command under `billing/commands/` to populate `metadata.plan` for all active subscriptions that are missing it, so the fallback becomes unreachable over time.