{"record":{"id":"12a355c7516c6a8d","repo":"koala73/worldmonitor","slug":"grant-not-found","errorCode":"GRANT_NOT_FOUND","errorMessage":"GRANT_NOT_FOUND","messagePattern":"GRANT_NOT_FOUND","errorType":"error_code","errorClass":"ConvexError","httpStatus":null,"severity":"error","filePath":"convex/payments/businessSeats.ts","lineNumber":417,"sourceCode":"        createdAt: g.createdAt,\n        acceptedAt: g.acceptedAt ?? null,\n        expiresAt: g.expiresAt,\n      })),\n    };\n  },\n});\n\n/**\n * Owner-only removal of a single seat. Revokes the grant and recomputes the\n * invitee's entitlement.\n */\nexport const removeSeat = mutation({\n  args: { grantId: v.id(\"businessProGrants\") },\n  handler: async (ctx, args) => {\n    const userId = await requireUserId(ctx);\n    const grant = await ctx.db.get(args.grantId);\n    if (!grant) {\n      throw new ConvexError({ kind: \"GRANT_NOT_FOUND\" });\n    }\n    if (grant.ownerUserId !== userId) {\n      throw new ConvexError({ kind: \"NOT_OWNER\" });\n    }\n    if (grant.status !== \"pending\" && grant.status !== \"accepted\") {\n      return { ok: true as const, status: \"already_inactive\" as const };\n    }\n\n    const now = Date.now();\n    // Serialize with inviteSeats via the per-Business-subscription lock row.\n    await touchBusinessSeatLock(ctx, grant.businessSubscriptionId, now);\n\n    await ctx.db.patch(args.grantId, { status: \"revoked\" });\n\n    if (grant.inviteeUserId) {\n      await ctx.runMutation(\n        internal.payments.subscriptionHelpers.recomputeEntitlementForUser,\n        { userId: grant.inviteeUserId, eventTimestamp: now },","sourceCodeStart":399,"sourceCodeEnd":435,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/convex/payments/businessSeats.ts#L399-L435","documentation":"Structured ConvexError thrown by the removeSeat mutation when the supplied businessProGrants id does not exist in the database (unknown or already-deleted grant). The owner-only removal guard cannot proceed without a grant row.","triggerScenarios":"Thrown at convex/payments/businessSeats.ts:421 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Refresh the seat list — the grant may have already been removed","Pass the exact grant id returned by the seat listing query"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"7d06c8633d256c18e38133030bc3613976a96ec9","analyzedAt":"2026-08-21T16:51:25.751Z","contentChangedAt":"2026-08-21T16:51:25.751Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}