{"record":{"id":"44c18a5edf5037a2","repo":"koala73/worldmonitor","slug":"company-monitoring-claim-policy-migration-required","errorCode":null,"errorMessage":"COMPANY_MONITORING_CLAIM_POLICY_MIGRATION_REQUIRED","messagePattern":"COMPANY_MONITORING_CLAIM_POLICY_MIGRATION_REQUIRED","errorType":"exception","errorClass":"ConvexError","httpStatus":null,"severity":"error","filePath":"convex/companyMonitoring/orchestration.ts","lineNumber":235,"sourceCode":"    exa: COMPANY_MONITORING_ROLLOUT_FLAGS.exaProvider,\n    x: COMPANY_MONITORING_ROLLOUT_FLAGS.xProvider,\n  };\n  return flags[source];\n}\n\nfunction enabledSources(): Source[] {\n  return ([\"exa\", \"x\"] as const).filter(providerRolloutEnabled);\n}\n\nfunction requireProviderClaimPolicy(\n  account: Doc<\"companyMonitoringAccounts\">,\n  source: Source,\n): void {\n  if (\n    providerRolloutEnabled(source) &&\n    !hasCurrentCompanyMonitoringClaimPolicy(account)\n  ) {\n    throw new ConvexError(\"COMPANY_MONITORING_CLAIM_POLICY_MIGRATION_REQUIRED\");\n  }\n}\n\nasync function updateAccountDueFromWork(ctx: MutationCtx, ownerAccountId: string) {\n  const account = await ctx.db\n    .query(\"companyMonitoringAccounts\")\n    .withIndex(\"by_logicalAccountId\", (q) => q.eq(\"logicalAccountId\", ownerAccountId))\n    .unique();\n  if (!account) return;\n  const nextForSource = async (source: Source) => {\n    const [due, leased] = await Promise.all([\n      ctx.db\n        .query(\"companyMonitoringScanWorkItems\")\n        .withIndex(\"by_account_source_state_selectionDueAt\", (q) =>\n          q.eq(\"ownerAccountId\", ownerAccountId).eq(\"source\", source).eq(\"state\", \"due\"),\n        )\n        .first(),\n      ctx.db","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/koala73/worldmonitor/blob/ffec79ac339946fd2d24e85845da5755dcaa534b/convex/companyMonitoring/orchestration.ts#L217-L253","documentation":"Thrown by requireProviderClaimPolicy when a provider source is rollout-enabled (COMPANY_MONITORING_ROLLOUT_FLAGS) but the account row does not have the current company-monitoring claim policy (hasCurrentCompanyMonitoringClaimPolicy returns false). This forces accounts to be migrated to the current claim-policy schema before provider work runs for them.","triggerScenarios":"Scheduling or claiming work for a rollout-enabled provider (exa/x) on an account whose claim policy is missing or out of date.","commonSituations":"A new claim-policy version shipped and existing accounts were not backfilled; rollout flag flipped on before the migration completed for an account; account created before the policy field existed.","solutions":["Run the account claim-policy migration/backfill so hasCurrentCompanyMonitoringClaimPolicy returns true for the affected account.","If the rollout is premature, disable the provider flag in COMPANY_MONITORING_ROLLOUT_FLAGS until migration finishes.","Confirm the account row writes the current policy version on creation and on policy upgrades."],"exampleFix":"// before — account predates policy v2, work scheduling fails\n\n// after — backfill account to current policy\nawait ctx.db.patch(account._id, {\n  claimPolicyVersion: CURRENT_CLAIM_POLICY_VERSION,\n  claimPolicyAppliedAt: Date.now(),\n});","handlingStrategy":"validation","validationCode":"if (providerRolloutEnabled(source) && !hasCurrentCompanyMonitoringClaimPolicy(account)) {\n  throw new Error(\"account requires claim-policy migration before scheduling\");\n}","typeGuard":"function accountReadyForProvider(account: unknown, source: string): boolean {\n  return !providerRolloutEnabled(source) || hasCurrentCompanyMonitoringClaimPolicy(account);\n}","tryCatchPattern":null,"preventionTips":["Backfill accounts to the current claim-policy version before flipping rollout flags.","Write the current policy version on account creation and on policy upgrades."],"tags":["convex","migration","rollout","policy","company-monitoring"],"backgroundTag":null,"analyzedSha":"ffec79ac339946fd2d24e85845da5755dcaa534b","analyzedAt":"2026-08-12T11:24:56.012Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}