koala73/worldmonitor · error · ConvexError

BUSINESS_NOT_ACTIVE

BUSINESS_NOT_ACTIVE

Error message

BUSINESS_NOT_ACTIVE

What it means

At accept time, `acceptBusinessInvite` looks up the Business subscription by `grant.businessSubscriptionId` and requires it to (a) exist, (b) have `planKey === "api_business"`, and (c) be covering at the current time via `isCoveringAt`. If any fails — typically because the owner cancelled, lapsed, or downgraded between sending the invite and the accept — the invite cannot be honored.

Source

Thrown at convex/payments/businessSeats.ts:494

    }
    if (grant.inviteeEmail !== inviteeEmail) {
      throw new ConvexError({ kind: "INVITE_EMAIL_MISMATCH" });
    }
    if (!sameDomain(grant.inviteeEmail, inviteeEmail)) {
      throw new ConvexError({ kind: "INVITE_EMAIL_MISMATCH" });
    }
    if (!isCorporateDomain(inviteeEmail)) {
      throw new ConvexError({ kind: "INVITEE_DOMAIN_NOT_CORPORATE" });
    }

    const businessSub = await ctx.db
      .query("subscriptions")
      .withIndex("by_dodoSubscriptionId", (q) =>
        q.eq("dodoSubscriptionId", grant.businessSubscriptionId),
      )
      .unique();
    if (!businessSub || businessSub.planKey !== "api_business" || !isCoveringAt(businessSub, now)) {
      throw new ConvexError({ kind: "BUSINESS_NOT_ACTIVE" });
    }

    await ctx.db.patch(args.grantId, {
      status: "accepted",
      inviteeUserId: userId,
      acceptedAt: now,
    });

    await ctx.runMutation(
      internal.payments.subscriptionHelpers.recomputeEntitlementForUser,
      { userId, eventTimestamp: now },
    );

    return { ok: true as const };
  },
});

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Have the owner reactivate or repurchase the `api_business` subscription, then accept again (a fresh grant may be needed if the grant was revoked on lapse)
  2. If the owner believes the subscription is active, verify the `subscriptions` row's covering window and planKey
  3. Note: grants are auto-revoked when the Business subscription stops covering, so BUSINESS_NOT_ACTIVE often co-occurs with a grant already cleaned up
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await convex.mutation(api.payments.businessSeats.acceptBusinessInvite, { grantId, token });
} catch (err) {
  if (err.data?.kind === 'BUSINESS_NOT_ACTIVE') {
    // inform user the owner's Business plan is no longer active; suggest contacting owner
  } else { throw err; }
}

Prevention

When it happens

Trigger: The owner's Business subscription is no longer active/covering when the invitee clicks accept: cancelled, payment failed past grace, or the planKey changed away from `api_business`.

Common situations: Owner cancelled the Business plan after sending invites; a payment failure ended coverage; subscription was downgraded to an individual plan; grant outlived the subscription that issued it.

Related errors


AI-assisted analysis of koala73/worldmonitor@ffec79ac33 (2026-08-12). Data as JSON: /api/errors/451266076803d943. Report an issue: GitHub.