koala73/worldmonitor · error · Error
[runDailyRamp] rampCurve
Error message
[runDailyRamp] rampCurve[${nextTier}] is undefined despite bounds check — config corruption? What it means
Defensive invariant guard in runDailyRamp: rampCurve[nextTier] is undefined even though the nextTier < rampCurve.length bounds check just passed. This should be unreachable and indicates the persisted broadcastRampConfig.rampCurve array is corrupted — mutated between the check and the access, or written with holes.
Solutions
- Inspect the broadcastRampConfig document's rampCurve array for holes, non-numeric entries, or concurrent modification
- Re-run configureRamp to rewrite a clean rampCurve and resume the ramp
- Add a validation step in configureRamp that rejects sparse or malformed rampCurve arrays before they persist
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at convex/broadcast/rampRunner.ts:1025 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/e9727c4f5a77917d.
Report an issue: GitHub.
Appendix: source
Thrown at convex/broadcast/rampRunner.ts:1027
}
}
// ──── Step 2: figure out which tier to send next ────
const nextTier = row.currentTier + 1;
if (nextTier >= row.rampCurve.length) {
console.log("[runDailyRamp] ramp curve complete — deactivating");
await ctx.runMutation(
internal.broadcast.rampRunner._recordRunOutcome,
{ status: "ramp-complete", deactivate: true },
);
return { status: "ramp-complete" };
}
// Bounds-checked above; explicit guard quiets noUncheckedIndexedAccess
// and protects against a future code change that breaks the
// bounds check above without realising this index is now unsafe.
const count = row.rampCurve[nextTier];
if (count === undefined) {
throw new Error(
`[runDailyRamp] rampCurve[${nextTier}] is undefined despite bounds check — config corruption?`,
);
}
const waveLabel = `${row.waveLabelPrefix}-${nextTier + row.waveLabelOffset}`;
// ──── Step 3: in-flight guard via the new wave-loading state machine ────
// PR 2 (post-launch-stabilization plan, 2026-04-29) replaces the
// monolithic assignAndExportWave + createProLaunchBroadcast + sendProLaunchBroadcast
// chain with a self-driving multi-step pipeline that fits within the
// Convex 10-min action runtime budget at any wave size. The state lives
// on `waveRuns` + `wavePickedContacts`. See `convex/broadcast/waveRuns.ts`.
//
// The legacy `_claimTierForRun` + `_recordPendingExport` + `_recordPendingBroadcast`
// + `_recordWaveSent` + `_recordRunOutcome` mutations remain in this
// module so the operator-recovery commands (`recoverFromPartialFailure`,
// `clearPartialFailure`, `forceReleaseLease`) keep working on any
// legacy partial-failure rows. New runs go through the state machine.
//View on GitHub (pinned to 7d06c8633d)