koala73/worldmonitor · error · Error

Account changed while

Error message

Account changed while ${action}. Try again.

What it means

Error thrown by requireCurrentConvexUser when the signed-in Clerk user id no longer matches the current Convex user record — the authenticated identity changed mid-session (account switch or re-auth) while a billing action was in flight. Retrying after re-sync resolves it.

Solutions

  1. Retry the action after the new session settles
  2. Ensure Clerk/Convex identity sync completes after account switches
  3. Avoid switching accounts while a billing dialog is open
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at src/services/billing.ts:81 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-08-21). Data as JSON: /api/errors/f8a243a0016a4b15. Report an issue: GitHub.

Appendix: source

Thrown at src/services/billing.ts:86

  if (typeof DOMException !== 'undefined' && err instanceof DOMException) {
    return new Error(`[billing] ${action}: ${err.name}: ${err.message}`, { cause: err });
  }
  const rendered = err === undefined ? 'undefined' : String(err);
  return new Error(`[billing] ${action} threw non-Error: ${rendered}`, { cause: err });
}

function requireSignedInUserId(action: string): string {
  const userId = getCurrentClerkUser()?.id;
  if (!userId) throw new Error(`Sign in to ${action}.`);
  return userId;
}

async function requireCurrentConvexUser(
  userId: string,
  action: string,
): Promise<void> {
  if (!await waitForConvexAuthForUser(userId)) {
    throw new Error(`Account changed while ${action}. Try again.`);
  }
  assertAccountStillCurrent(userId, action);
}

/**
 * Initialize the subscription watch for the authenticated user.
 * Idempotent -- calling multiple times is a no-op after the first.
 * Failures are logged but never thrown (dashboard must not break).
 */
export async function initSubscriptionWatch(
  _userId?: string,
  isCurrent: () => boolean = () => true,
): Promise<void> {
  const isExpectedAccount = (): boolean => (
    isCurrent() && (_userId === undefined || getCurrentClerkUser()?.id === _userId)
  );
  if (initialized || !isExpectedAccount()) return;

View on GitHub (pinned to 7d06c8633d)