koala73/worldmonitor · error · Error

[_recordPendingExport] lease lost: expected runId=

Error message

[_recordPendingExport] lease lost: expected runId=${args.runId}, found ${row.pendingRunId ?? "<cleared>"}. Refusing to persist export progress — operator/another run owns the state.

What it means

Error "[_recordPendingExport] lease lost: expected runId=${args.runId}, found ${row.pendingRunId ?? "<cleared>"}. Refusing to persist export progress — operator/another run owns the state." thrown in koala73/worldmonitor.

Solutions

  1. Identify what cleared or replaced the lease (forceReleaseLease call, another run claiming) from Convex logs before touching state
  2. Do not retry the export — re-running could double-send the wave; use recoverFromPartialFailure against any persisted progress instead
  3. If operator intervention was intentional, let the owning run proceed and abandon this one
Defensive patterns

Strategy: validation

When it happens

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

Appendix: source

Thrown at convex/broadcast/rampRunner.ts:722

 * metadata if the action dies between this point and a successful
 * `_recordWaveSent`.
 *
 * Lease-validating: throws if the lease has changed (operator
 * `forceReleaseLease` mid-flight, or a different run claimed). The throw
 * bubbles to Convex auto-Sentry; the runner stops without advancing.
 */
export const _recordPendingExport = internalMutation({
  args: {
    runId: v.string(),
    waveLabel: v.string(),
    segmentId: v.string(),
    assigned: v.number(),
  },
  handler: async (ctx, args) => {
    const row = await loadConfig(ctx);
    if (!row) throw new Error("[_recordPendingExport] no ramp configured");
    if (row.pendingRunId !== args.runId) {
      throw new Error(
        `[_recordPendingExport] lease lost: expected runId=${args.runId}, found ${row.pendingRunId ?? "<cleared>"}. Refusing to persist export progress — operator/another run owns the state.`,
      );
    }
    await ctx.db.patch(row._id, {
      pendingWaveLabel: args.waveLabel,
      pendingSegmentId: args.segmentId,
      pendingAssigned: args.assigned,
      pendingExportAt: Date.now(),
    });
    return { ok: true as const };
  },
});

/**
 * Persist post-`createProLaunchBroadcast` progress. Called by the runner
 * AFTER `createProLaunchBroadcast` returns successfully. Lets
 * `recoverFromPartialFailure` recover the broadcastId without
 * operator-supplied metadata if the action dies between this point and a

View on GitHub (pinned to 7d06c8633d)