koala73/worldmonitor · error · Error

[pickWaveAction] could not claim lease: ${claim.reason} (cur

Error message

[pickWaveAction] could not claim lease: ${claim.reason} (current: ${claim.current})

What it means

Lease acquisition failure in pickWaveAction: _claimWaveRunLease refused the claim (the reason and current holder are embedded). Another wave run is active or a stale lease is held, so this pick cannot start without double-sending risk.

Source

Thrown at convex/broadcast/waveRuns.ts:722

    }
    if (args.waveLabel.length === 0 || args.waveLabel.length > 64) {
      throw new Error("[pickWaveAction] waveLabel must be 1-64 chars");
    }
    const batchSize = args.batchSize ?? DEFAULT_BATCH_SIZE;
    const excludeNonEnglish = args.excludeNonEnglish === true;

    // Step 1: claim lease + insert waveRuns row.
    const claim: ClaimLeaseResult = await ctx.runMutation(
      internal.broadcast.waveRuns._claimWaveRunLease,
      {
        waveLabel: args.waveLabel,
        runId: args.runId,
        requestedCount: args.requestedCount,
        batchSize,
      },
    );
    if (!claim.ok) {
      throw new Error(
        `[pickWaveAction] could not claim lease: ${claim.reason}` +
        (claim.current ? ` (current: ${claim.current})` : ""),
      );
    }

    try {
      // Step 2: stream registrations + filter (per-page) + reservoir-sample.
      const [suppressed, paid] = await Promise.all([
        ctx.runQuery(internal.broadcast.waveRuns._getSuppressedEmails, {}),
        ctx.runQuery(internal.broadcast.waveRuns._getPaidEmails, {}),
      ]);
      const suppressedSet = new Set(suppressed);
      const paidSet = new Set(paid);

      const reservoir = new Reservoir<string>(args.requestedCount);
      // Pool-filter audit accumulators — persisted to waveRuns at end of pool
      // selection so any past wave's filter behavior is auditable from the
      // row alone (no log archaeology).

View on GitHub (pinned to eeab0a219f)

Solutions

  1. Read the embedded reason: a live lease means wait for the current wave to finish; a stale lease means use the documented lease-release or recovery flow
  2. Do not bypass the lease — retrying concurrently risks duplicate segments and sends
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at convex/broadcast/waveRuns.ts:722 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21). Data as JSON: /api/errors/d2d913aa04fc2099. Report an issue: GitHub.