koala73/worldmonitor · error · Error

[createProLaunchBroadcast] Resend ${res.status}: ${body}

Error message

[createProLaunchBroadcast] Resend ${res.status}: ${body}

What it means

Thrown when the Resend POST /broadcasts endpoint returns a non-2xx status during createProLaunchBroadcast. The error includes the HTTP status code and the raw response body (or '<no body>' if the body read itself failed). This is a passthrough of the upstream Resend API error — the message format is `[createProLaunchBroadcast] Resend <status>: <body>`.

Source

Thrown at convex/broadcast/sendBroadcast.ts:112

      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${apiKey}`,
        "User-Agent": USER_AGENT,
      },
      body: JSON.stringify({
        name,
        segment_id: segmentId,
        from: PRO_LAUNCH_FROM,
        reply_to: PRO_LAUNCH_REPLY_TO,
        subject: PRO_LAUNCH_SUBJECT,
        html: PRO_LAUNCH_HTML,
        text: PRO_LAUNCH_TEXT,
      }),
    });

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

    const json = (await res.json().catch(() => null)) as {
      id?: string;
    } | null;
    if (!json?.id) {
      throw new Error(
        `[createProLaunchBroadcast] Resend response missing id: ${JSON.stringify(json)}`,
      );
    }

    return {
      broadcastId: json.id,
      name,
      segmentId,
      subject: PRO_LAUNCH_SUBJECT,

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Read the embedded status code and body: 401/403 means the RESEND_API_KEY Convex env var is wrong/expired — rotate it in the Resend dashboard and update the Convex variable. 422 usually means the segmentId or from-address is invalid — verify both in the Resend dashboard. 429 means back off and retry.
  2. Verify the segmentId exists in the same Resend workspace the API key belongs to.
  3. Confirm PRO_LAUNCH_FROM ('Elie from WorldMonitor <news@worldmonitor.app>') is a verified sender identity in Resend.
  4. For 5xx or 429, retry createProLaunchBroadcast after a short backoff — the action is not idempotent, so check the Resend dashboard first to avoid creating a duplicate broadcast.
Defensive patterns

Strategy: retry

Try / catch

try {
  const result = await ctx.runAction(internal.broadcast.sendBroadcast.createProLaunchBroadcast, { segmentId });
  // store result.broadcastId
} catch (err) {
  const msg = String(err);
  if (msg.includes("Resend 429") || msg.includes("Resend 5")) {
    // transient — back off and retry, but check Resend dashboard for duplicates first
    await sleep(backoffMs);
    throw err; // re-throw for scheduler retry
  }
  if (msg.includes("Resend 401") || msg.includes("Resend 403")) {
    // API key issue — do not retry; surface to operator
    throw err;
  }
  // 422/404 — segmentId or from-address invalid; do not retry blindly
  throw err;
}

Prevention

When it happens

Trigger: Calling createProLaunchBroadcast with an invalid or deleted segmentId (Resend 404/422). Using an expired or revoked RESEND_API_KEY (401/403). Hitting Resend rate limits (429). Resend service outage or 5xx. The 'from' address PRO_LAUNCH_FROM not verified in the Resend account (422).

Common situations: The segmentId was copied from the wrong Resend workspace. The API key was rotated in the Resend dashboard but the Convex env var was not updated. The 'from' domain news@worldmonitor.app lost its DNS verification. A transient Resend outage coincides with the send window.

Related errors


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