koala73/worldmonitor · error · Error

[createProLaunchBroadcast] RESEND_API_KEY not set

Error message

[createProLaunchBroadcast] RESEND_API_KEY not set

What it means

createProLaunchBroadcast is a Convex internalAction that calls Resend's POST /broadcasts endpoint to create a broadcast from a locked segment. It reads process.env.RESEND_API_KEY and throws if unset before making any network call, so a missing key fails fast rather than producing an opaque 401 from Resend. The same env var must be configured in the Convex deployment's environment variables.

Source

Thrown at convex/broadcast/sendBroadcast.ts:68

/**
 * Create a Resend Broadcast from the locked launch content. Does NOT
 * send — separate `sendProLaunchBroadcast` step. Returns the new
 * broadcast id so the operator can preview in the Resend dashboard
 * before firing.
 *
 * Idempotency: NOT idempotent on segmentId. Calling twice with the same
 * segment creates two separate broadcasts. The operator owns "have I
 * already created this?" tracking.
 */
export const createProLaunchBroadcast = internalAction({
  args: {
    segmentId: v.string(),
    nameSuffix: v.optional(v.string()),
  },
  handler: async (_ctx, { segmentId, nameSuffix }) => {
    const apiKey = process.env.RESEND_API_KEY;
    if (!apiKey) {
      throw new Error("[createProLaunchBroadcast] RESEND_API_KEY not set");
    }

    // Hard-gate: refuse to ship the placeholder physical address.
    // CAN-SPAM requires a valid postal address in every commercial
    // email footer; sending the literal "physical address TBD" string
    // is non-compliant and embarrassing. Edit
    // `PRO_LAUNCH_PHYSICAL_ADDRESS` in proLaunchEmailContent.ts to the
    // real postal address before invoking this action.
    if (
      PRO_LAUNCH_PHYSICAL_ADDRESS.includes("TBD") ||
      PRO_LAUNCH_PHYSICAL_ADDRESS.includes("placeholder")
    ) {
      throw new Error(
        `[createProLaunchBroadcast] PRO_LAUNCH_PHYSICAL_ADDRESS is still a placeholder ("${PRO_LAUNCH_PHYSICAL_ADDRESS}"). ` +
          "Set the real CAN-SPAM postal address in convex/broadcast/proLaunchEmailContent.ts before sending.",
      );
    }

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Set the secret in the target Convex deployment: `npx convex env set RESEND_API_KEY <key>` (or via the Convex dashboard), then redeploy if required.
  2. Confirm you are calling from the deployment that has the secret (check CONVEX_DEPLOYMENT), not a preview without it.
  3. Verify the key is non-empty and a valid Resend key (re_*).

Example fix

// before — action throws if env missing
await ctx.runAction(internal.broadcast.sendBroadcast.createProLaunchBroadcast, {
  segmentId,
});

// after — guard at the caller (operator tooling) before invoking
if (!process.env.RESEND_API_KEY) {
  throw new Error('RESEND_API_KEY not set in this deployment. Run: npx convex env set RESEND_API_KEY <key>');
}
await ctx.runAction(internal.broadcast.sendBroadcast.createProLaunchBroadcast, { segmentId });
Defensive patterns

Strategy: validation

Validate before calling

// Guard at the operator/caller layer before invoking the action
if (!process.env.RESEND_API_KEY) {
  throw new Error('RESEND_API_KEY not set in this Convex deployment. Run: npx convex env set RESEND_API_KEY <key>');
}
await ctx.runAction(internal.broadcast.sendBroadcast.createProLaunchBroadcast, { segmentId });

Type guard

function hasResendKey(env: NodeJS.ProcessEnv): env is NodeJS.ProcessEnv & { RESEND_API_KEY: string } {
  return typeof env.RESEND_API_KEY === 'string' && env.RESEND_API_KEY.length > 0;
}

Prevention

When it happens

Trigger: Invoking createProLaunchBroadcast in a Convex deployment where the RESEND_API_KEY environment variable was never set; running in a fresh preview/dev deployment without the secret; the secret was deleted or renamed.

Common situations: New/staging Convex project without secrets provisioned; secret name typo; production secret rotation removed the old key before the new one was set.

Related errors


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