koala73/worldmonitor · error · Error

[_recordWaveSent] lease lost: expected runId=

Error message

[_recordWaveSent] lease lost: expected runId=${args.runId}, found ${row.pendingRunId ?? "<cleared>"}. Refusing to advance tier — investigate what cleared the lease.

What it means

Error "[_recordWaveSent] lease lost: expected runId=${args.runId}, found ${row.pendingRunId ?? "<cleared>"}. Refusing to advance tier — investigate what cleared the lease." thrown in koala73/worldmonitor.

Solutions

  1. Identify what cleared or replaced pendingRunId: another ramp run started, an admin cancelled the ramp, or a competing _recordWaveSent from a stale worker
  2. Check the ramp config document's history and current pendingRunId to see which run now owns the lease
  3. Discard this run's in-flight wave results; the current lease owner is responsible for tier advancement
  4. Audit other mutations that write pendingRunId and ensure only the lease holder clears or rotates it
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at convex/broadcast/rampRunner.ts:792 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/93e8e959ba65641e. Report an issue: GitHub.

Appendix: source

Thrown at convex/broadcast/rampRunner.ts:794

    waveLabel: v.string(),
    broadcastId: v.string(),
    segmentId: v.string(),
    assigned: v.number(),
    sentAt: v.number(),
  },
  handler: async (ctx, args) => {
    const row = await loadConfig(ctx);
    if (!row) throw new Error("[_recordWaveSent] no ramp configured");
    if (row.currentTier !== args.expectedCurrentTier) {
      throw new Error(
        `[_recordWaveSent] tier moved underneath us: expected ${args.expectedCurrentTier}, found ${row.currentTier}. Refusing to overwrite.`,
      );
    }
    if (row.pendingRunId !== args.runId) {
      // The lease changed under us — operator force-released it, or
      // recoverFromPartialFailure cleared it. We must NOT advance the tier;
      // bubble to Convex auto-Sentry so ops can investigate.
      throw new Error(
        `[_recordWaveSent] lease lost: expected runId=${args.runId}, found ${row.pendingRunId ?? "<cleared>"}. Refusing to advance tier — investigate what cleared the lease.`,
      );
    }
    await ctx.db.patch(row._id, {
      currentTier: args.newTier,
      lastWaveLabel: args.waveLabel,
      lastWaveBroadcastId: args.broadcastId,
      lastWaveSegmentId: args.segmentId,
      lastWaveAssigned: args.assigned,
      lastWaveSentAt: args.sentAt,
      lastRunStatus: "succeeded",
      lastRunAt: Date.now(),
      lastRunError: undefined,
      pendingRunId: undefined,
      pendingRunStartedAt: undefined,
      // Clear all per-step progress markers — this run's state is now in
      // the lastWave* fields and the markers would otherwise leak into the
      // next run's recovery surface.

View on GitHub (pinned to 7d06c8633d)