koala73/worldmonitor · error · ConvexError
activation outcome buckets must be disjoint and contain at m
Error message
activation outcome buckets must be disjoint and contain at most ${proActivationStepIdValidator.members.length} steps What it means
ConvexError guard validating the Pro activation outcome step buckets: confirmedSteps, skippedSteps, blockedSteps, and failedSteps combined must contain no duplicates and no more entries than the total number of known activation steps. Fires when a client double-reports a step in two buckets or fabricates unknown/duplicate step ids.
Source
Thrown at convex/payments/billing.ts:997
!Number.isSafeInteger(args.revision) ||
args.revision < 1 ||
args.revision > MAX_PRO_ACTIVATION_OUTCOME_REVISION
) {
throw new ConvexError(
`activation outcome revision must be an integer from 1 to ${MAX_PRO_ACTIVATION_OUTCOME_REVISION}`,
);
}
const allSteps = [
...args.confirmedSteps,
...args.skippedSteps,
...(args.blockedSteps ?? []),
...args.failedSteps,
];
if (
allSteps.length > proActivationStepIdValidator.members.length ||
new Set(allSteps).size !== allSteps.length
) {
throw new ConvexError(
`activation outcome buckets must be disjoint and contain at most ${proActivationStepIdValidator.members.length} steps`,
);
}
if (args.revision <= (presentation.outcomeRevision ?? 0)) {
return false;
}
const now = Date.now();
await ctx.db.patch(presentation._id, {
confirmedSteps: args.confirmedSteps,
skippedSteps: args.skippedSteps,
// Written straight from the arg, NOT coerced to []. Convex removes a
// field patched as `undefined`, so a client too old to report blocked
// steps leaves the field ABSENT ("could not report") instead of claiming
// "none were blocked" — a claim that is actively false for that client,
// which classified denials as skips. Absent is also what lets an analyst
// exclude those rows from a denial rate. Every snapshot stays a full
// replacement either way: an explicit [] clears, and so does absence.View on GitHub (pinned to 9361220cc0)
Solutions
- Place each step id in exactly one outcome bucket per revision
- Use only step ids from proActivationStepIdValidator's known members
- Rebuild the buckets client-side from the actual per-step outcomes before submitting
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at convex/payments/billing.ts:981 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of koala73/worldmonitor@9361220cc0 (2026-08-21).
Data as JSON: /api/errors/0c8ac9ed0bea28c8.
Report an issue: GitHub.