koala73/worldmonitor · critical · Error

[createProLaunchBroadcast] PRO_LAUNCH_PHYSICAL_ADDRESS is st

Error message

[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.

What it means

Hard-gate thrown by createProLaunchBroadcast when PRO_LAUNCH_PHYSICAL_ADDRESS (imported from proLaunchEmailContent.ts) still contains the substring 'TBD' or 'placeholder'. The guard exists because CAN-SPAM requires a valid postal address in every commercial email footer; shipping the literal placeholder string would be non-compliant. It is a deliberate pre-flight check that fires before any Resend API call is made.

Source

Thrown at convex/broadcast/sendBroadcast.ts:81

    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.",
      );
    }

    const name =
      nameSuffix && nameSuffix.length > 0
        ? `PRO Launch — ${nameSuffix}`
        : `PRO Launch — ${new Date().toISOString().slice(0, 10)}`;

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

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Edit PRO_LAUNCH_PHYSICAL_ADDRESS in convex/broadcast/proLaunchEmailContent.ts to the real company postal address (currently 'WorldMonitor FZ LLC, Dubai - United Arab Emirates' — confirm it is still correct).
  2. Ensure the new value contains neither 'TBD' nor 'placeholder' as a substring (the check is case-sensitive on those exact lowercase strings).
  3. Re-run createProLaunchBroadcast after redeploying the Convex function so the updated constant is loaded.

Example fix

// before
export const PRO_LAUNCH_PHYSICAL_ADDRESS = "physical address TBD";
// after
export const PRO_LAUNCH_PHYSICAL_ADDRESS = "WorldMonitor FZ LLC, Dubai - United Arab Emirates";
Defensive patterns

Strategy: validation

Validate before calling

import { PRO_LAUNCH_PHYSICAL_ADDRESS } from "./proLaunchEmailContent";

function assertPhysicalAddressReady(): void {
  if (PRO_LAUNCH_PHYSICAL_ADDRESS.includes("TBD") || PRO_LAUNCH_PHYSICAL_ADDRESS.includes("placeholder")) {
    throw new Error("PRO_LAUNCH_PHYSICAL_ADDRESS is a placeholder — set the real CAN-SPAM address first.");
  }
}
// call before createProLaunchBroadcast

Prevention

When it happens

Trigger: Invoking createProLaunchBroadcast via `npx convex run broadcast/sendBroadcast:createProLaunchBroadcast '{"segmentId":"seg_xxx"}'` while PRO_LAUNCH_PHYSICAL_ADDRESS in convex/broadcast/proLaunchEmailContent.ts is set to a value containing 'TBD' or 'placeholder' (e.g. 'physical address TBD'). Also fires if a future edit reintroduces either substring.

Common situations: A developer clones the repo and the address constant is still the placeholder default. An operator reverts proLaunchEmailContent.ts during a merge conflict resolution and the placeholder comes back. The address was intentionally set to a temporary string during content drafting and never replaced before the send window.

Related errors


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