koala73/worldmonitor · error · Error

[sendProLaunchBroadcast] Resend ${res.status}: ${errBody}

Error message

[sendProLaunchBroadcast] Resend ${res.status}: ${errBody}

What it means

Thrown when Resend's POST /broadcasts/{broadcastId}/send endpoint returns a non-2xx status during sendProLaunchBroadcast. The error includes the HTTP status and raw response body. This is the send (fire) step — the broadcast was already created successfully.

Source

Thrown at convex/broadcast/sendBroadcast.ts:174

    const body: Record<string, unknown> = {};
    if (scheduledAt) body.scheduled_at = scheduledAt;

    const res = await fetch(
      `${RESEND_API_BASE}/broadcasts/${encodeURIComponent(broadcastId)}/send`,
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${apiKey}`,
          "User-Agent": USER_AGENT,
        },
        body: JSON.stringify(body),
      },
    );

    if (!res.ok) {
      const errBody = await res.text().catch(() => "<no body>");
      throw new Error(
        `[sendProLaunchBroadcast] Resend ${res.status}: ${errBody}`,
      );
    }

    return {
      broadcastId,
      status: scheduledAt ? "scheduled" : "queued",
      scheduledAt: scheduledAt ?? null,
    };
  },
});

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Check the status code: 404/409 means the broadcastId is gone or already sent — inspect the Resend dashboard to determine the true state before retrying.
  2. If 409 (already sent), do NOT retry; instead record the send state in the waveRuns row to prevent re-sending.
  3. For 429 or 5xx, retry with exponential backoff — the send endpoint is designed to be retryable for transient failures.
  4. If the broadcast was deleted, create a new one via createProLaunchBroadcast and send the new id.
Defensive patterns

Strategy: retry

Try / catch

try {
  await ctx.runAction(internal.broadcast.sendBroadcast.sendProLaunchBroadcast, { broadcastId });
} catch (err) {
  const msg = String(err);
  if (msg.includes("Resend 409")) {
    // already sent — record state, do not retry
    throw new Error(`Broadcast ${broadcastId} already sent or in conflict`);
  }
  if (msg.includes("Resend 404")) {
    // broadcastId gone — recreate via createProLaunchBroadcast
    throw err;
  }
  if (msg.includes("Resend 429") || msg.includes("Resend 5")) {
    // transient — retry with backoff
    throw err; // let scheduler retry
  }
  throw err;
}

Prevention

When it happens

Trigger: The broadcastId does not exist or was already sent (Resend 404/409). The broadcast was deleted between create and send. Rate limiting (429). Resend 5xx outage. The RESEND_API_KEY lacks send permissions for this broadcast.

Common situations: The operator created a broadcast, then deleted it in the Resend dashboard before sending. The same broadcastId was sent twice (double-click, duplicate schedule). A Resend outage occurs between broadcast creation and the send call. The broadcast was already sent by a previous run that did not record its result.

Related errors


AI-assisted analysis of koala73/worldmonitor@ffec79ac33 (2026-08-12). Data as JSON: /api/errors/1dd6e12e6971255f. Report an issue: GitHub.