Skip to content

A failed appendRows may poison the seenMessages dedupe so the exporter's retry silently writes nothing #879

Description

@philcunliffe

Surfaced by an automated review sweep over the claude telemetry plugin. Not yet verified by the reconcile loop: treat the claim below as a lead with file:line evidence, and reproduce it with a failing-then-passing test before fixing. If it does not reproduce, say so and close.

The claim

hypaware-core/plugins-workspace/claude/src/telemetry/source.js:688 rethrows on a write failure so the exporter retries. The retry is claimed not to recover the batch:

  • deps.gateway.recordProjectedExchange reaches exchange_writer.js record(), which calls aiGatewayRowsFromProjectedExchange.
  • That adds every message's identity.messageId to the writer's process-lifetime state.seenMessages while building rows (message_projector.js:773), i.e. before storage.appendRows runs.
  • If appendRows throws (disk full, transient Iceberg/spool write error), source.js rethrows, the listener answers HTTP 500, and Claude Code re-POSTs the same batch.
  • The second record() now hits state.seenMessages.has(...) for every message, continues, and returns rows.length === 0.

Claimed consequence: the batch's user prompts and assistant responses are permanently lost (only transcript backfill can recover them), while rowsWritten reports 0 as though there had been nothing to write - a silent loss, not an error.

Acceptance

A regression test that fails on current master: force appendRows to throw once, re-deliver the identical batch, and assert the rows land on the retry. Today they should be dropped. If the dedupe set is only populated after a successful append, the claim is wrong and this issue should be closed with that evidence.

Metadata

Metadata

Assignees

No one assigned

    Labels

    neutral:fixDelegate this issue to neutral for an autonomous fix attempt (reproduce -> fix -> PR)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions