koala73/worldmonitor · error · ConvexError
INPUT_TOO_LARGE
INPUT_TOO_LARGE
Error message
INPUT_TOO_LARGE
What it means
Thrown by `mergeAnonymousLocal` (Step 3) when `args.countries.length > MAX_MERGE_INPUT`. This is a defensive upper-bound to prevent an enormous payload from a tampered client or a corrupted local-store from doing unbounded work in the ISO2-filter loop and subsequent per-country inserts. Carries `{ kind: "INPUT_TOO_LARGE", max: MAX_MERGE_INPUT, received }`. Distinct from INVALID_COUNTRY (per-code) and EMPTY_INPUT.
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, aView on GitHub (pinned to ffec79ac33)
Solutions
- Client-side: cap the local follows array before calling; `countries.slice(0, MAX_MERGE_INPUT)`.
- On `err.data.kind === "INPUT_TOO_LARGE"`, truncate and retry, or investigate why local state exceeds the bound (likely a bug).
- If the legitimate use case exceeds the cap, raise `MAX_MERGE_INPUT` in the mutation — do not silently drop.
Example fix
// before
await convex.mutation(api.followedCountries.mergeAnonymousLocal, { countries: allFollows });
// after
const MAX = 100; // keep in sync with server MAX_MERGE_INPUT
const capped = allFollows.slice(0, MAX);
if (allFollows.length > MAX) console.warn("truncating merge input", allFollows.length);
await convex.mutation(api.followedCountries.mergeAnonymousLocal, { countries: capped }); Defensive patterns
Strategy: validation
Validate before calling
const MAX_MERGE_INPUT = 100; // keep in sync with server
const capped = localFollows.slice(0, MAX_MERGE_INPUT);
if (localFollows.length > MAX_MERGE_INPUT) {
console.warn("merge input exceeds cap; truncating", localFollows.length);
}
if (capped.length === 0) return; Type guard
function withinMergeCap(countries: string[]): boolean {
return countries.length > 0 && countries.length <= MAX_MERGE_INPUT;
} Try / catch
try {
await convex.mutation(api.followedCountries.mergeAnonymousLocal, { countries: capped });
} catch (err) {
if (err.data?.kind === "INPUT_TOO_LARGE") {
await convex.mutation(api.followedCountries.mergeAnonymousLocal, { countries: localFollows.slice(0, err.data.max) });
} else throw err;
} Prevention
- Cap the local follows array client-side to MAX_MERGE_INPUT.
- Investigate if local state legitimately exceeds the cap (likely a bug).
- Read err.data.max from the error for the authoritative bound.
- Don't silently drop — decide explicitly whether to truncate or raise the cap.
When it happens
Trigger: Calling the mutation with an array larger than `MAX_MERGE_INPUT`; a corrupted/anonymized local-store holding thousands of entries; a client that accidentally passes a paginated/global country list instead of the user's follows.
Common situations: A bug where the entire ISO country registry (~250 codes) is passed instead of the user's selections; a test fixture with a huge array; a tampered client attempting to flood the merge.
Related errors
- EMPTY_INPUT
- INCOMPATIBLE_DELIVERY
- COUNTRIES_LIMIT_EXCEEDED
- TICKERS_LIMIT_EXCEEDED
- digestHour must be an integer 0–23
AI-assisted analysis of koala73/worldmonitor@ffec79ac33 (2026-08-12).
Data as JSON: /api/errors/12a3b8364789a5ea.
Report an issue: GitHub.