{"record":{"id":"015352ef981c16b1","repo":"koala73/worldmonitor","slug":"invitee-domain-not-corporate","errorCode":"INVITEE_DOMAIN_NOT_CORPORATE","errorMessage":"INVITEE_DOMAIN_NOT_CORPORATE","messagePattern":"INVITEE_DOMAIN_NOT_CORPORATE","errorType":"error_code","errorClass":"ConvexError","httpStatus":null,"severity":"error","filePath":"convex/payments/businessSeats.ts","lineNumber":184,"sourceCode":"    const existingByEmail = new Map(\n      existingGrants.map((g) => [g.inviteeEmail, g]),\n    );\n\n    // Separate new invites from duplicates before the cap check so a duplicate\n    // re-invite is idempotent even when the cap is full.\n    const newEmails: string[] = [];\n    const results: Array<{\n      email: string;\n      grantId: string;\n      status: \"created\" | \"already_pending\" | \"already_accepted\";\n    }> = [];\n\n    for (const email of emails) {\n      if (email === normalizedOwnerEmail) {\n        throw new ConvexError({ kind: \"CANNOT_INVITE_SELF\" });\n      }\n      if (!isCorporateDomain(email)) {\n        throw new ConvexError({ kind: \"INVITEE_DOMAIN_NOT_CORPORATE\" });\n      }\n\n      const existing = existingByEmail.get(email);\n      if (existing) {\n        if (existing.status === \"accepted\") {\n          results.push({ email, grantId: existing._id, status: \"already_accepted\" });\n          continue;\n        }\n        if (existing.status === \"pending\" && existing.expiresAt > now) {\n          results.push({ email, grantId: existing._id, status: \"already_pending\" });\n          continue;\n        }\n      }\n      newEmails.push(email);\n    }\n\n    const currentCount = await countActiveOrPendingGrants(\n      ctx,","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/convex/payments/businessSeats.ts#L166-L202","documentation":"Thrown by convex/payments/businessSeats.ts when a business seat invitation is rejected because the invitee's email domain does not qualify as a corporate domain. Business seat plans require invitees to belong to an approved corporate email domain (free/public providers like gmail.com, yahoo.com are rejected). The check fails before the invitation is created or billed, so no seat charge occurs.","triggerScenarios":"Thrown at convex/payments/businessSeats.ts:185 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Ask the invitee to use their corporate email address associated with the purchasing organization.","Have an admin add the invitee's domain to the organization's approved corporate domain list, then retry the invitation.","If the invitee genuinely cannot use a corporate email, transfer or assign the seat directly to an existing verified user instead of inviting by email.","Verify the organization's domain settings were not recently changed and re-run the invitation after correcting them."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"7d06c8633d256c18e38133030bc3613976a96ec9","analyzedAt":"2026-09-01T10:32:37.851Z","contentChangedAt":"2026-09-01T10:32:37.851Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}