koala73/worldmonitor · error · ConvexError

INPUT_TOO_LARGE

INPUT_TOO_LARGE

Error message

INPUT_TOO_LARGE

What it means

Guard in mergeAnonymousLocal: args.countries exceeds the maximum allowed merge batch size (INPUT_TOO_LARGE kind). The cap backs the server-side free-user limit — a merge must never be able to balloon a free account past the follow cap in one call.

Solutions

  1. Chunk the local countries list into batches within the limit and merge sequentially
  2. Cap anonymous local storage client-side so it can never exceed the merge limit
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at convex/followedCountries.ts:502 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at convex/followedCountries.ts:502

 * downgrade is a separate concern handled by NOT auto-deleting on
 * downgrade; merge is the FIRST sign-in and has no PRO history to
 * grandfather.)
 */
export const mergeAnonymousLocal = mutation({
  args: { countries: v.array(v.string()) },
  handler: async (ctx, args): Promise<MergeAnonymousLocalResult> => {
    const identity = await ctx.auth.getUserIdentity();
    if (!identity) throw new ConvexError({ kind: "UNAUTHENTICATED" });
    const userId = identity.subject;

    // Step 2: empty-input guard.
    if (args.countries.length === 0) {
      throw new ConvexError({ kind: "EMPTY_INPUT" });
    }

    // Step 3: defensive upper-bound on input length.
    if (args.countries.length > MAX_MERGE_INPUT) {
      throw new ConvexError({
        kind: "INPUT_TOO_LARGE",
        max: MAX_MERGE_INPUT,
        received: args.countries.length,
      });
    }

    // Step 4: ISO-2 registry filter; collect droppedInvalid in input order.
    const droppedInvalid: string[] = [];
    const validInputs: string[] = [];
    for (const code of args.countries) {
      if (isValidIso2(code)) {
        validInputs.push(code);
      } else {
        droppedInvalid.push(code);
      }
    }

    // Step 5: canonicalize — dedupe in first-seen order. Without this, a

View on GitHub (pinned to eeab0a219f)