koala73/worldmonitor · error · Error

[initRamp] ramp already configured (active=${existing.active

Error message

[initRamp] ramp already configured (active=${existing.active}, tier=${existing.currentTier}). Run abortRamp first if reconfiguring.

What it means

Thrown by initRamp when a broadcastRampConfig row already exists for RAMP_KEY. initRamp is a one-shot setup that refuses to overwrite an existing active or inactive config — the operator must run abortRamp first to clear the prior config before reconfiguring mid-launch. This prevents silently swapping a live ramp's curve/state.

Source

Thrown at convex/broadcast/rampRunner.ts:189

    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,
      waveLabelOffset: offset,
      bounceKillThreshold:
        args.bounceKillThreshold ?? DEFAULT_BOUNCE_KILL_THRESHOLD,
      complaintKillThreshold:
        args.complaintKillThreshold ?? DEFAULT_COMPLAINT_KILL_THRESHOLD,
      killGateTripped: false,
      lastWaveBroadcastId: args.seedLastWaveBroadcastId,
      lastWaveSentAt: args.seedLastWaveSentAt,
      lastWaveLabel: args.seedLastWaveLabel,

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Run abortRamp first to clear the existing config, then call initRamp.
  2. If the existing ramp is still desired, do not call initRamp — use the appropriate tuning mutation instead.
  3. Confirm via the broadcastRampConfig row that abortRamp actually removed the config before retrying init.

Example fix

// before
await initRamp(ctx, { rampCurve: [...], waveLabelPrefix: "w" }); // ramp already configured
// after — abort first, then init
await abortRamp(ctx, {});
await initRamp(ctx, { rampCurve: [...], waveLabelPrefix: "w" });
Defensive patterns

Strategy: validation

Validate before calling

const existing = await ctx.db.query("broadcastRampConfig")
  .withIndex("by_key", q => q.eq("key", RAMP_KEY)).first();
if (existing) {
  await abortRamp(ctx, {});
}
await initRamp(ctx, args);

Try / catch

try {
  await initRamp(ctx, args);
} catch (e) {
  if (e.message.includes("ramp already configured")) {
    await abortRamp(ctx, {});
    await initRamp(ctx, args);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling initRamp when a config row for RAMP_KEY already exists (active or paused); reconfiguring a ramp without first aborting the existing one; a prior initRamp succeeded and a second call is attempted.

Common situations: Operator wants to change the ramp curve mid-launch; a previous ramp was paused (not aborted) and a new init is attempted; accidental double-invocation of initRamp.

Related errors


AI-assisted analysis of koala73/worldmonitor@ffec79ac33 (2026-08-12). Data as JSON: /api/errors/053cb7298c86e26a. Report an issue: GitHub.