koala73/worldmonitor · error · Error

[recoverFromPartialFailure] no ramp configured

Error message

[recoverFromPartialFailure] no ramp configured

What it means

recoverFromPartialFailure is the operator recovery path for a partial-failure wave. It loads the config via loadConfig and throws if no row exists, because there is no partial-failure state to recover from on a non-existent ramp.

Source

Thrown at convex/broadcast/rampRunner.ts:371

export const recoverFromPartialFailure = internalMutation({
  args: {
    recovery: v.union(
      v.literal("manual-finished"),
      v.literal("discard-and-rotate"),
    ),
    reason: v.string(),
    // For recovery==='manual-finished'. Fall back to persisted pending*
    // markers when omitted; sentAt is ALWAYS operator-supplied (no progress
    // marker captures send-completion time).
    broadcastId: v.optional(v.string()),
    segmentId: v.optional(v.string()),
    sentAt: v.optional(v.number()),
    assigned: v.optional(v.number()),
    waveLabel: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    const row = await loadConfig(ctx);
    if (!row) throw new Error("[recoverFromPartialFailure] no ramp configured");
    if (row.lastRunStatus !== "partial-failure") {
      return {
        ok: true as const,
        noop: true as const,
        currentStatus: row.lastRunStatus,
      };
    }

    const clearPending = {
      pendingRunId: undefined,
      pendingRunStartedAt: undefined,
      pendingWaveLabel: undefined,
      pendingSegmentId: undefined,
      pendingAssigned: undefined,
      pendingExportAt: undefined,
      pendingBroadcastId: undefined,
      pendingBroadcastAt: undefined,
    } as const;

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Preflight with getRampStatus; if {configured:false} there is nothing to recover.
  2. If abortRamp already ran, the partial-failure state was removed with the row — re-seed with initRamp if launching again.
  3. Confirm the correct Convex deployment is targeted.

Example fix

// before
await ctx.runMutation(internal.broadcast.rampRunner.recoverFromPartialFailure, { recovery: 'manual-finished', reason });

// after
const status = await ctx.runQuery(internal.broadcast.rampRunner.getRampStatus, {});
if (!status.configured) return { skipped: 'no ramp configured' };
await ctx.runMutation(internal.broadcast.rampRunner.recoverFromPartialFailure, { recovery: 'manual-finished', reason });
Defensive patterns

Strategy: validation

Validate before calling

// Preflight before recoverFromPartialFailure
const status = await ctx.runQuery(internal.broadcast.rampRunner.getRampStatus, {});
if (!status.configured) {
  return { skipped: 'no ramp configured — nothing to recover' };
}

Type guard

function isConfigured(s: { configured: boolean }): s is { configured: true; lastRunStatus?: string } {
  return s.configured === true;
}

Prevention

When it happens

Trigger: Calling recoverFromPartialFailure before initRamp, after abortRamp deleted the row, or in an unseeded deployment.

Common situations: Recovery runbook executed after the ramp was already aborted; automation targeting the wrong Convex project.

Related errors


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