{"record":{"id":"dc5ea24de7e94353","repo":"koala73/worldmonitor","slug":"company-monitoring-access-denied-dc5ea2","errorCode":null,"errorMessage":"COMPANY_MONITORING_ACCESS_DENIED","messagePattern":"COMPANY_MONITORING_ACCESS_DENIED","errorType":"exception","errorClass":"ConvexError","httpStatus":null,"severity":"error","filePath":"convex/companyMonitoring/_shared.ts","lineNumber":100,"sourceCode":"    entitlement.planKey !== \"free\" &&\n    entitlement.features.tier > 0 &&\n    entitlement.validUntil >= Date.now(),\n  );\n  if (\n    !account ||\n    !activeEntitlement ||\n    account.lifecycle !== \"entitled\" ||\n    account.ownerUserId !== ownerUserId ||\n    account.terminalReason\n  ) {\n    return null;\n  }\n  return account;\n}\n\nexport async function requireActiveAccount(ctx: CompanyMonitoringCtx, ownerUserId: string) {\n  const account = await activeAccountForOwner(ctx, ownerUserId);\n  if (!account) throw new ConvexError(\"COMPANY_MONITORING_ACCESS_DENIED\");\n  return account;\n}\n\ntype CustomerClaimType =\n  | \"alias\"\n  | \"domain\"\n  | \"legal_identifier\"\n  | \"x_account_id\"\n  | \"x_handle\"\n  | \"location\"\n  | \"customer_reference\";\n\nexport function customerClaimAllowedUses(type: CustomerClaimType) {\n  if (\n    type === \"alias\" ||\n    type === \"domain\" ||\n    type === \"legal_identifier\" ||\n    type === \"x_account_id\" ||","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/koala73/worldmonitor/blob/ffec79ac339946fd2d24e85845da5755dcaa534b/convex/companyMonitoring/_shared.ts#L82-L118","documentation":"Thrown by requireActiveAccount (_shared.ts:98-101) when activeAccountForOwner returns null — meaning no active, entitled, non-terminal companyMonitoringAccounts row exists for the given ownerUserId. A ConvexError with this exact message surfaces to the client as a 4xx-style application error. This guards every Company Monitoring entry point that requires a live entitled account.","triggerScenarios":"Calling a Company Monitoring mutation/query for a user who has no entitlement (free plan), whose entitlement expired (validUntil < now), whose account lifecycle is not 'entitled', whose account has a terminalReason set, or whose account ownerUserId does not match. Also when the account simply does not exist yet (never provisioned).","commonSituations":"A free-plan user attempts to use Company Monitoring features. A user's PRO subscription lapsed and the account transitioned to 'entitlement_lapsed'. The user's account was terminalized (owner_deleted/account_deleted). The account was never provisioned because the entitlement write path hasn't synced yet.","solutions":["Gate the client-side UI on the user's entitlement status before allowing the action — do not call Company Monitoring endpoints for free/lapsed users.","If the user should be entitled, verify their entitlements row exists and validUntil >= now via `npx convex run` or the dashboard.","If the account was never provisioned, trigger syncCompanyMonitoringAccountFromEntitlement (via an entitlement write or a provisioned entry point like requireProvisionedAccount).","If the account was terminalized in error, investigate the terminalReason and lifecycleSequence in the companyMonitoringAccounts row."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before calling a Company Monitoring endpoint, check entitlement client-side:\nconst entitled = entitlement && entitlement.planKey !== \"free\" && entitlement.features.tier > 0 && entitlement.validUntil >= Date.now();\nif (!entitled) {\n  // show upgrade/paywall UI instead of calling the backend\n}","typeGuard":null,"tryCatchPattern":"try {\n  await ctx.runMutation(internal.companyMonitoring.someEndpoint, args);\n} catch (err) {\n  if (err instanceof ConvexError && err.message === \"COMPANY_MONITORING_ACCESS_DENIED\") {\n    // surface a paywall/upgrade prompt to the user\n    throw new Error(\"Company Monitoring requires an active PRO subscription.\");\n  }\n  throw err;\n}","preventionTips":["Gate Company Monitoring UI on the user's entitlement status before allowing actions.","Handle COMPANY_MONITORING_ACCESS_DENIED as a business-level 403 (show paywall), not a crash.","Ensure the account is provisioned via an entitlement write before the user first interacts with the feature."],"tags":["convex","entitlement","authorization","company-monitoring","access-control"],"backgroundTag":null,"analyzedSha":"ffec79ac339946fd2d24e85845da5755dcaa534b","analyzedAt":"2026-08-12T11:24:56.012Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}