koala73/worldmonitor · error · Error
[initRamp] rampCurve must be non-empty
Error message
[initRamp] rampCurve must be non-empty
What it means
Thrown by initRamp when args.rampCurve is an empty array. The ramp curve defines the per-wave recipient counts that escalate the broadcast, and an empty curve means the ramp has no tiers to progress through — the config would be a no-op. This is the first validation check in initRamp.
Source
Thrown at convex/broadcast/rampRunner.ts:166
// Required as a pair when `waveLabelOffset > 0` (operational
// signal that the ramp is resuming after manual waves). The very
// first wave ever (offset=0) is exempt because there is no prior.
seedLastWaveBroadcastId: v.optional(v.string()),
seedLastWaveSentAt: v.optional(v.number()),
seedLastWaveLabel: v.optional(v.string()),
seedLastWaveSegmentId: v.optional(v.string()),
seedLastWaveAssigned: v.optional(v.number()),
// Locale filter — when true, pickWaveAction excludes contacts with
// non-English locale (canonical via `users.localePrimary`, fallback
// via email-TLD heuristic for legacy waitlist registrants without a
// users row). Default false to preserve byte-identical behavior for
// existing ramps. Operators opt in for wave-8+ deliberately. Run
// `_dryRunNonEnglishExclusion` first to inspect impact before flipping.
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.dbView on GitHub (pinned to ffec79ac33)
Solutions
- Provide a non-empty rampCurve, e.g. [100, 250, 500, 1000] escalating per wave.
- Validate the curve is non-empty in the ramp-config script before calling initRamp.
- Confirm the config source actually contains the intended curve values.
Example fix
// before
await initRamp(ctx, { rampCurve: [], waveLabelPrefix: "w" });
// after
await initRamp(ctx, { rampCurve: [100, 250, 500, 1000], waveLabelPrefix: "w" }); Defensive patterns
Strategy: validation
Validate before calling
if (!Array.isArray(rampCurve) || rampCurve.length === 0) {
throw new Error("rampCurve must be a non-empty array");
}
await initRamp(ctx, { rampCurve, waveLabelPrefix }); Type guard
function isNonEmptyCurve(c: unknown): c is number[] {
return Array.isArray(c) && c.length > 0;
} Prevention
- Validate rampCurve is non-empty in the config-builder script.
- Unit-test initRamp with an empty array to confirm it rejects.
- Keep ramp curves in a versioned config file.
When it happens
Trigger: Calling initRamp with rampCurve: []; passing an array that was dynamically constructed and ended up empty (e.g. a generator that produced no entries); a config typo where the curve was omitted/forgotten.
Common situations: A ramp-config script defaulted the curve to [] and wasn't filled in; the curve was read from a config file with a missing/empty rampCurve key; test invocation forgot to populate the curve.
Related errors
- [initRamp] seedLastWaveBroadcastId and seedLastWaveSentAt mu
- [initRamp] waveLabelOffset=${offset} signals resumption afte
- [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/139734933e8580d3.
Report an issue: GitHub.