koala73/worldmonitor · error · Error

[_finalizeWaveRun] run ${runId} missing broadcastId/segmentI

Error message

[_finalizeWaveRun] run ${runId} missing broadcastId/segmentId

What it means

State guard in _finalizeWaveRun: the run is in 'broadcast-created' status but its row lacks broadcastId and/or segmentId. Finalize must record what was sent, so it refuses to advance the tier with incomplete send metadata; reaching here means the status transitioned without the ids being persisted.

Source

Thrown at convex/broadcast/waveRuns.ts:1425

      .withIndex("by_runId", (q) => q.eq("runId", runId))
      .unique();
    if (!run) throw new Error(`[_finalizeWaveRun] no run ${runId}`);

    // Status check FIRST — broadcastId presence is downstream of being in
    // broadcast-created status. Checking presence before status would mask
    // a wrong-status caller behind a misleading "missing broadcastId" error.
    if (run.status === "sent") {
      // Idempotent: a duplicate finalize on an already-sent run is a no-op,
      // not an error. Don't re-advance the tier.
      return { ok: true as const, alreadySent: true as const, advancedToTier: undefined };
    }
    if (run.status !== "broadcast-created") {
      throw new Error(
        `[_finalizeWaveRun] run ${runId} is ${run.status}, expected broadcast-created`,
      );
    }
    if (!run.broadcastId || !run.segmentId) {
      throw new Error(
        `[_finalizeWaveRun] run ${runId} missing broadcastId/segmentId`,
      );
    }

    const config = await ctx.db
      .query("broadcastRampConfig")
      .withIndex("by_key", (q) => q.eq("key", "current"))
      .unique();
    if (!config) throw new Error("[_finalizeWaveRun] no broadcastRampConfig");
    if (config.pendingRunId !== runId) {
      throw new Error(
        `[_finalizeWaveRun] lost lease: expected ${runId}, found ${config.pendingRunId ?? "<cleared>"}. ` +
        `Refusing to advance tier — operator force-released the lease, or another run took over.`,
      );
    }

    const now = Date.now();
    const nextTier = config.currentTier + 1;

View on GitHub (pinned to eeab0a219f)

Solutions

  1. Look up the broadcast and segment in the Resend dashboard and recover the run's missing ids via the documented recovery flow
  2. Audit _markBroadcastCreated and _markPickComplete to ensure the ids are always persisted with the status transition
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at convex/broadcast/waveRuns.ts:1425 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/3fca6b7aacfb69e4. Report an issue: GitHub.