Skip to main content
← Back to list
01Issue
BugOpenSwamp Club
AssigneesNone

Relationships

#1603 CLI has never sent insert_id: retried telemetry batches are double-counted into cli_daily, inflating XP in an append-only ledger

Opened by keeb · 8/11/2026

Summary

HttpTelemetrySender.sendBatch has never sent an insert_id. swamp-club's ingest queue carries a unique index on that field specifically to deduplicate a re-POST, and its own comment names swamp as the emitter that gets this wrong. Every retry of an already-accepted batch has therefore been landing as a second queue doc and double-counting into cli_daily — which feeds the activity projector and the score ledger.

The forward fix ships in swamp-club/swamp#2117 (a one-line change, found while fixing swamp-club#1591). This issue is about the inflation already banked, which that PR does not and cannot address.

Evidence

services/telemetry/lib/db.ts:78-81 (swamp-club), verbatim:

Idempotent ingest for emitters that supply a client-side insert_id (reliableTrack does; legacy/CLI emitters get a server-generated one): a retried POST re-sends the accepted key, and without this it becomes a new queue doc in a LATER batch, duplicated into every consumer — the Mongo consumers dedup via their *_processed_inserts collections, but ClickHouse would double-count cli_daily (permanent XP inflation; the per-batch insert_deduplication_token can't see across batches).

And toEventDoc (services/telemetry/lib/schema.ts:255):

insert_id: input.insert_id ?? crypto.randomUUID(),

The CLI sender sent only { event, distinct_id, properties }, so it took the crypto.randomUUID() branch on every POST — including retries of a batch the server had already accepted.

When this fires

TelemetryService.doFlush only marks entries flushed after a successful send. Any path where the server accepts a batch but the client does not learn it re-sends the whole batch on the next invocation:

  • A 202 lost to a network drop, or to the sender's own 5s AbortSignal.timeout firing after the server committed.
  • The 2s flush timeout in the CLI teardown (cli/mod.ts:1619) expiring mid-request.
  • Any process death between the server's commit and the local markFlushed.

Batches are up to 25 entries, so one lost ack inflates up to 25 invocations at once.

Impact

swamp.cli_daily_mv counts every cli_invocation row with result.status = 'success', and the activity projector values that count with no dedup of its own. Duplicates therefore raise cnt, which raises granted units. The ledger is explicitly append-only — activity-asof-projector.sql states points already banked are never clawed back — so this is not self-correcting.

Magnitude is unknown and may well be negligible. That is the point of filing: it has never been measured.

Suggested next step

Duplicates are retroactively detectable, because the entry's own UUID is carried in the payload as properties.id and is stable across retries even though insert_id was not. Roughly:

SELECT count() AS dup_groups, sum(n - 1) AS surplus_rows
FROM (
  SELECT JSONExtractString(properties, 'id') AS entry_id, count() AS n
  FROM swamp.events
  WHERE event = 'cli_invocation'
  GROUP BY entry_id
  HAVING n > 1
);

That gives the surplus row count directly. If it is material, decide deliberately whether to correct it or accept it and note it — a silent correction to an append-only ledger is worse than a documented one.

Environment

  • swamp CLI, all versions prior to swamp-club/swamp#2117
  • Applies to the interactive CLI path, not just daemons — this predates and is independent of swamp-club#1591
  • swamp-club/swamp#2117 — sends insert_id: entry.id, stopping further inflation
  • #1591 — serve telemetry gap, where this was discovered
  • #1254 — telemetry stats consumer dedup ordering (different layer, same field)
  • #820 — telemetry watcher replica coordination (shipped)
02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED

Open

8/11/2026, 4:02:45 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack728/11/2026, 8:02:54 PM
stack72 unassigned stack728/11/2026, 9:33:06 PM

Sign in to post a ripple.