koala73/worldmonitor · error · Error

[forceReleaseLease] no ramp configured

Error message

[forceReleaseLease] no ramp configured

What it means

Operator guard in the forceReleaseLease internal mutation: loadConfig returned no broadcastRampConfig row, so there is no lease to force-release. The last-resort wedge-recovery tool cannot run because the ramp was never configured on this deployment.

Solutions

  1. Run configureRamp before using lease-recovery tooling
  2. Confirm the deployment actually has a ramp — a missing config row usually means wrong environment
Defensive patterns

Strategy: validation

When it happens

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

Appendix: source

Thrown at convex/broadcast/rampRunner.ts:672

/**
 * Operator-only last-resort lease release.
 *
 * Use ONLY when a cron action is genuinely wedged (process died silently
 * between claim and any catch block, leaving a held lease with no
 * partial-failure status). Investigate Convex action logs + Resend dashboard
 * BEFORE calling this — the side effects might have actually completed
 * (segment created, broadcast sent) and the right recovery is then
 * `recoverFromPartialFailure({recovery:"manual-finished"})`, not a fresh send.
 *
 * Sets `lastRunStatus = "partial-failure"` so `recoverFromPartialFailure`
 * picks up; preserves any `pending*` progress markers so the operator can
 * decide between manual-finished and discard-and-rotate from persisted state.
 */
export const forceReleaseLease = internalMutation({
  args: { reason: v.string() },
  handler: async (ctx, { reason }) => {
    const row = await loadConfig(ctx);
    if (!row) throw new Error("[forceReleaseLease] no ramp configured");
    if (!row.pendingRunId) {
      return {
        ok: true as const,
        noop: true as const,
        currentStatus: row.lastRunStatus,
      };
    }
    const releasedRunId = row.pendingRunId;
    const heldForMs =
      row.pendingRunStartedAt !== undefined
        ? Date.now() - row.pendingRunStartedAt
        : undefined;
    await ctx.db.patch(row._id, {
      pendingRunId: undefined,
      pendingRunStartedAt: undefined,
      lastRunStatus: "partial-failure",
      lastRunAt: Date.now(),
      lastRunError: `forced-release: ${reason.slice(0, 200)} (was held by ${releasedRunId}${heldForMs !== undefined ? `, age ${Math.round(heldForMs / 1000)}s` : ""})`,

View on GitHub (pinned to 7d06c8633d)