koala73/worldmonitor · error · Error
[initRamp] waveLabelOffset=${offset} signals resumption afte
Error message
[initRamp] waveLabelOffset=${offset} signals resumption after manual waves; seedLastWaveBroadcastId + seedLastWaveSentAt are required so the first cron tick can apply the kill-gate against the prior wave. Pass them, or set waveLabelOffset=0 to start a fresh ramp. What it means
Thrown by initRamp when waveLabelOffset > 0 (signaling the ramp resumes after one or more manually-sent waves) but the seed pair (seedLastWaveBroadcastId + seedLastWaveSentAt) is not provided. The first cron tick must apply the kill-gate against the prior wave, which requires the seed broadcast id and timestamp. Without them, the kill-gate would be silently skipped — a dangerous failure mode.
Source
Thrown at convex/broadcast/rampRunner.ts:180
excludeNonEnglish: v.optional(v.boolean()),
},
handler: async (ctx, args) => {
if (args.rampCurve.length === 0) {
throw new Error("[initRamp] rampCurve must be non-empty");
}
if (args.rampCurve.some((n) => !Number.isInteger(n) || n <= 0)) {
throw new Error("[initRamp] rampCurve entries must be positive integers");
}
const offset = args.waveLabelOffset ?? 0;
const hasSeedBroadcast = !!args.seedLastWaveBroadcastId;
const hasSeedSentAt = typeof args.seedLastWaveSentAt === "number";
if (hasSeedBroadcast !== hasSeedSentAt) {
throw new Error(
"[initRamp] seedLastWaveBroadcastId and seedLastWaveSentAt must be provided together.",
);
}
if (offset > 0 && !hasSeedBroadcast) {
throw new Error(
`[initRamp] waveLabelOffset=${offset} signals resumption after manual waves; seedLastWaveBroadcastId + seedLastWaveSentAt are required so the first cron tick can apply the kill-gate against the prior wave. Pass them, or set waveLabelOffset=0 to start a fresh ramp.`,
);
}
const existing = await ctx.db
.query("broadcastRampConfig")
.withIndex("by_key", (q) => q.eq("key", RAMP_KEY))
.first();
if (existing) {
throw new Error(
`[initRamp] ramp already configured (active=${existing.active}, tier=${existing.currentTier}). Run abortRamp first if reconfiguring.`,
);
}
await ctx.db.insert("broadcastRampConfig", {
key: RAMP_KEY,
active: true,
rampCurve: args.rampCurve,
currentTier: -1,
waveLabelPrefix: args.waveLabelPrefix,View on GitHub (pinned to ffec79ac33)
Solutions
- Provide seedLastWaveBroadcastId and seedLastWaveSentAt when waveLabelOffset > 0, so the first cron tick can evaluate the kill-gate against the prior wave.
- Alternatively, set waveLabelOffset=0 to start a fresh ramp with no prior waves (no seed needed).
- Follow the resume-ramp runbook: capture the last manual wave's broadcast id and sent timestamp before calling initRamp.
Example fix
// before
await initRamp(ctx, {
rampCurve: [500, 1000], waveLabelPrefix: "w",
waveLabelOffset: 7, // signals resumption, but no seed
});
// after — seed the prior wave
await initRamp(ctx, {
rampCurve: [500, 1000], waveLabelPrefix: "w",
waveLabelOffset: 7,
seedLastWaveBroadcastId: "last-broadcast-id",
seedLastWaveSentAt: Date.parse("2024-10-14T00:00:00Z"),
}); Defensive patterns
Strategy: validation
Validate before calling
const offset = args.waveLabelOffset ?? 0;
if (offset > 0 && (!args.seedLastWaveBroadcastId || typeof args.seedLastWaveSentAt !== "number")) {
throw new Error("waveLabelOffset > 0 requires seedLastWaveBroadcastId + seedLastWaveSentAt");
}
await initRamp(ctx, args); Prevention
- Follow the resume-ramp runbook: capture the last manual wave's id and timestamp before init.
- For fresh ramps, leave waveLabelOffset at 0 to avoid the seed requirement.
- Validate the resume/seed invariant in a config-lint step.
When it happens
Trigger: Calling initRamp with waveLabelOffset set to a positive number (e.g. 7, meaning waves 0-6 were sent manually) but without seedLastWaveBroadcastId and seedLastWaveSentAt; resuming a ramp after manual waves and forgetting to seed the prior-wave state.
Common situations: Operator sent several waves manually before enabling the auto-ramp, then called initRamp with the offset but didn't pass the seed values; a resume-ramp runbook step was skipped.
Related errors
- [initRamp] rampCurve must be non-empty
- [initRamp] seedLastWaveBroadcastId and seedLastWaveSentAt mu
- [initRamp] rampCurve entries must be positive integers
- [initRamp] ramp already configured (active=${existing.active
- [backfillCanary250] RESEND_API_KEY not set — run with the sa
AI-assisted analysis of koala73/worldmonitor@ffec79ac33 (2026-08-12).
Data as JSON: /api/errors/2d7dcaf9c3a2d600.
Report an issue: GitHub.