{"record":{"id":"f874fde33a9f914d","repo":"koala73/worldmonitor","slug":"not-found-f874fd","errorCode":null,"errorMessage":"NOT_FOUND","messagePattern":"NOT_FOUND","errorType":"exception","errorClass":"ConvexError","httpStatus":null,"severity":"error","filePath":"convex/companyMonitoring/companies.ts","lineNumber":202,"sourceCode":"  },\n});\n\nexport const updateCompanyForOwner = internalMutation({\n  args: {\n    ownerUserId: v.string(),\n    companyId: v.string(),\n    patch: companyPatchValidator,\n  },\n  handler: async (ctx, args) => {\n    const account = await requireActiveAccount(ctx, args.ownerUserId);\n    const company = await ctx.db\n      .query(\"companyMonitoringCompanies\")\n      .withIndex(\"by_account_companyId\", (q) =>\n        q.eq(\"ownerAccountId\", account.logicalAccountId).eq(\"companyId\", args.companyId),\n      )\n      .unique();\n    if (!company || company.lifecycle === \"removed\" || !company.name || !company.domicileCountry) {\n      throw new ConvexError(\"NOT_FOUND\");\n    }\n    const patch = args.patch;\n    const addClaimInputs = patch.addClaims ?? [];\n    const removeClaimInputs = patch.removeClaimIds ?? [];\n    if (\n      addClaimInputs.length > COMPANY_MONITORING_LIMITS.maxClaimsPerCompany ||\n      removeClaimInputs.length > COMPANY_MONITORING_LIMITS.maxClaimsPerCompany\n    ) {\n      throw new ConvexError(\"INVALID_COMPANY_PATCH\");\n    }\n\n    const hasName = Object.prototype.hasOwnProperty.call(patch, \"name\");\n    const hasDomicile = Object.prototype.hasOwnProperty.call(patch, \"domicileCountry\");\n    const hasCustomerReference = Object.prototype.hasOwnProperty.call(patch, \"customerReference\");\n    const normalizedFields = normalizeMonitoredCompanyInput({\n      name: hasName ? patch.name! : company.name,\n      domicileCountry: hasDomicile ? patch.domicileCountry! : company.domicileCountry,\n      customerReference: hasCustomerReference","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/koala73/worldmonitor/blob/ffec79ac339946fd2d24e85845da5755dcaa534b/convex/companyMonitoring/companies.ts#L184-L220","documentation":"Thrown by the updateCompanyForOwner mutation when the target company cannot be patched. The lookup uses the by_account_companyId index scoped to the caller's logical account, so the row must belong to the authenticated owner. The guard also rejects companies whose lifecycle is 'removed' or whose required display fields (name, domicileCountry) have been purged, because a removed company is asynchronously purged and is no longer editable.","triggerScenarios":"Calling updateCompanyForOwner with a companyId that does not exist for this account, that belongs to a different account, that was previously set to 'removed' via setCompanyStateForOwner, or whose async purge (advanceCompanyPurge) has already nulled name/domicileCountry.","commonSituations":"Stale companyId held in the UI after the user removed the company in another session; race between a remove action and an in-flight update; typo or copy/paste of an ID from a different account; calling update on a company mid-purge.","solutions":["Verify the companyId still exists and is active/paused by listing via listCompaniesForOwner before attempting the update.","If the company was removed, create a new company with createCompanyForOwner instead of patching the removed row.","Handle NOT_FOUND in the caller by refreshing the company list and dropping the stale reference from local state."],"exampleFix":"// before\nawait ctx.runMutation(internal.companyMonitoring.companies.updateCompanyForOwner, {\n  ownerUserId, companyId: staleId, patch,\n});\n\n// after\nconst companies = await ctx.runQuery(internal.companyMonitoring.companies.listCompaniesForOwner, { ownerUserId });\nif (!companies.some((c) => c.companyId === staleId)) {\n  return { status: \"gone\" };\n}\nawait ctx.runMutation(internal.companyMonitoring.companies.updateCompanyForOwner, {\n  ownerUserId, companyId: staleId, patch,\n});","handlingStrategy":"validation","validationCode":"const companies = await ctx.runQuery(internal.companyMonitoring.companies.listCompaniesForOwner, { ownerUserId });\nconst exists = companies.some((c) => c.companyId === companyId);\nif (!exists) throw new UserError(\"Company no longer exists\");\nawait ctx.runMutation(internal.companyMonitoring.companies.updateCompanyForOwner, { ownerUserId, companyId, patch });","typeGuard":"function isEditableCompany(row: { lifecycle: string; name?: string; domicileCountry?: string }): boolean {\n  return row.lifecycle !== \"removed\" && Boolean(row.name) && Boolean(row.domicileCountry);\n}","tryCatchPattern":"try {\n  await updateCompanyForOwner(...);\n} catch (err) {\n  if (err instanceof ConvexError && err.message === \"NOT_FOUND\") {\n    // refresh company list, drop stale id\n  } else throw err;\n}","preventionTips":["Do not cache companyId across sessions without re-validating via listCompaniesForOwner.","Disable edit controls once a company enters the removed lifecycle."],"tags":["convex","not-found","company-monitoring","mutation"],"backgroundTag":null,"analyzedSha":"ffec79ac339946fd2d24e85845da5755dcaa534b","analyzedAt":"2026-08-12T11:24:56.012Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}