koala73/worldmonitor · error · Error

[assignAndExportWave] waveLabel "${waveLabel}" already has s

Error message

[assignAndExportWave] waveLabel "${waveLabel}" already has stamped rows — pick a unique label, or use the Resend dashboard to inspect/clean up the prior wave's segment first.

What it means

Thrown by assignAndExportWave when _hasWaveLabel returns true — i.e. registrations already exist stamped with the given waveLabel. This prevents overlapping waves that would double-send to the same recipients. The operator must use a unique label or clean up the prior wave's Resend segment first.

Source

Thrown at convex/broadcast/audienceWaveExport.ts:299

    }
    if (!Number.isFinite(count) || count <= 0) {
      throw new Error(
        `[assignAndExportWave] count must be a positive integer; got ${count}`,
      );
    }
    if (waveLabel.length === 0 || waveLabel.length > 64) {
      throw new Error(
        "[assignAndExportWave] waveLabel must be 1-64 chars",
      );
    }

    // Step 1: refuse to overlap with an existing wave.
    const exists = await ctx.runQuery(
      internal.broadcast.audienceWaveExport._hasWaveLabel,
      { waveLabel },
    );
    if (exists) {
      throw new Error(
        `[assignAndExportWave] waveLabel "${waveLabel}" already has stamped rows — pick a unique label, or use the Resend dashboard to inspect/clean up the prior wave's segment first.`,
      );
    }

    // Step 2: stream registrations, dedup, reservoir-sample N.
    const [suppressed, paid] = await Promise.all([
      ctx.runQuery(
        internal.broadcast.audienceWaveExport._getSuppressedEmails,
        {},
      ),
      ctx.runQuery(internal.broadcast.audienceWaveExport._getPaidEmails, {}),
    ]);
    const suppressedSet = new Set(suppressed);
    const paidSet = new Set(paid);

    const reservoir = new Reservoir<string>(count);
    let cursor: string | null = null;
    while (true) {

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Use a unique waveLabel for each assignAndExportWave invocation (e.g. append a counter or timestamp).
  2. Inspect the prior wave's stamped rows and Resend segment via the Resend dashboard before reusing a label.
  3. If the prior wave is genuinely superseded, pick a fresh label rather than trying to reuse it.

Example fix

// before
await assignAndExportWave(ctx, { waveLabel: "wave-7", count: 500 }); // already has stamped rows
// after — unique label per run
await assignAndExportWave(ctx, { waveLabel: `wave-7-${Date.now()}`, count: 500 });
Defensive patterns

Strategy: validation

Validate before calling

const exists = await ctx.runQuery(internal.broadcast.audienceWaveExport._hasWaveLabel, { waveLabel });
if (exists) throw new Error(`waveLabel ${waveLabel} already used — pick a new one`);
await assignAndExportWave(ctx, { waveLabel, count });

Try / catch

try {
  await assignAndExportWave(ctx, { waveLabel, count });
} catch (e) {
  if (e.message.includes("already has stamped rows")) {
    waveLabel = `${baseLabel}-${Date.now()}`; // unique suffix
    await assignAndExportWave(ctx, { waveLabel, count });
  } else throw e;
}

Prevention

When it happens

Trigger: Calling assignAndExportWave with a waveLabel that already appears in registrations.proLaunchWave (or wherever _hasWaveLabel checks); re-running a wave export with the same label after a partial or prior run; a label collision across manual and automated waves.

Common situations: Retrying a failed wave run with the same label instead of a new one; two operators using overlapping label schemes (e.g. both using '2024-01'); resuming an interrupted run without checking which label was already stamped.

Related errors


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