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
- Identify what cleared or replaced the lease (forceReleaseLease call, another run claiming) from Convex logs before touching state
- Do not retry the export — re-running could double-send the wave; use recoverFromPartialFailure against any persisted progress instead
- 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 aView on GitHub (pinned to 7d06c8633d)