Skip to content

test(listen): attribute missing binary deliveries and stop one late delivery failing later steps - #483

Merged
leggetter merged 1 commit into
mainfrom
fix/listen-binary-test-flake
Nov 2, 2026
Merged

leggetter merged 1 commit into
mainfrom
fix/listen-binary-test-flake

Conversation

@leggetter

Copy link
Copy Markdown
Collaborator

What

Makes the listen binary-body acceptance tests (test/acceptance/listen_binary_test.go) report why a delivery did not arrive, and stops one slow delivery from failing the steps after it. Tests only; no CLI code changes.

Why

These tests failed in 2 of 14 runs since they landed on 2026-10-02, both with Connected. Waiting for events... followed by no request reached the local app within 45s:

That message could not say where the event went, so the failure could not be attributed.

Root cause

Verified (reproduced locally, 2 failures in 15 looped runs of the listen tests, with debug logging and the API's view of each event):

  • The request was accepted and an event was created for the listening CLI, then stayed QUEUED with 0 attempts for 1 to 3 minutes. Meanwhile the CLI's websocket was connected and answering pings, and received no message. The one event that was eventually attempted was forwarded by the CLI and returned 200. So the delay is upstream of the CLI. It is not in the CLI's forwarding, and it is not a readiness race: the events were sent 11 s after the websocket connected, and sends made immediately after connecting were delivered every time (8 of 8 in a dedicated check, and every such send in the after-fix loop below).
  • The same stall also failed TestListenForwardsEventsWithoutTTY, which sends a JSON body. It is not specific to binary bodies, nor to the old-and-new-CLI test. The 2026-10-29 run shows the same thing: that test also timed out within the same three minutes.
  • Test-design bug that amplified it: localApp.next took whatever request arrived next. When a delayed event finally arrived, it was taken as the following step's delivery. That step then failed with a wrong Content-Type and a wrong file (reproduced: the jpeg step saved the 256-byte octet-stream body). So one slow delivery failed several steps, with misleading messages.

Not the cause:

  • Fixed 12 s sleeps: listen connects in about 1 s.
  • The two CLIs in the mixed test sharing a client: each hookdeck ci creates a distinct CLI client.
  • The 410 Resource was deleted warning: listen's cleanup had already deleted the connection, so the test's own delete found nothing. Noise.

Inferred, not verified here: why delivery to a connected CLI session stalls for minutes. This has been reported separately; it is not something the tests or the CLI can fix.

Change

  • Readiness: each test waits for listen's Connected. Waiting for events... line, which this CLI and v3.0.3 both print, instead of sleeping 12 s. It fails fast if listen exits.

  • Correlation: every request carries a unique X-Acceptance-Delivery-Id header. Each step waits for its own delivery and logs and skips any other, so a late delivery can no longer fail the next step.

  • A failure says where the event stopped. On timeout the test looks the request up by that header (gateway request list --search-term, then gateway event list --search-term) and reports:

    • the request's event counts;
    • each event's CLI, status, attempts and error code;
    • a one-line conclusion when the event was never attempted.

    listen now runs with --log-level debug. A failure prints its stdout plus only the websocket lines (connect, close, every incoming message), so it shows whether anything reached the session.

  • Cleanup: removed the redundant connection delete that produced the 410 warning.

The binary tests also run faster: 20 s to 9 s, 19 s to 8 s, and 55 s to 30 s.

The change is deliberately not a retry or a longer timeout. A stalled delivery still fails the test, now with a message that attributes it.

Testing

All local acceptance runs were made with no CI acceptance run in progress or queued (checked before each iteration).

  • go test -short ./pkg/...: exit 0
  • go vet ./...: exit 0
  • Before, ACCEPTANCE_SLICE=2 go test -tags=listen -run '<the three binary tests>|TestListenForwardsEventsWithoutTTY' ./test/acceptance/, looped 15 times: 13 passed, 2 failed. Both failures fell in one stall window: one in TestListenForwardsEventsWithoutTTY, one in TestListenForwardsBinaryFilesThatTheAppCanSave, where a single delayed event failed all five subtests.
  • After, the same command looped 15 times: 15 passed. Every send went out the moment listen reported it was connected, about 45 such sends in total, and all were delivered. This shows the readiness wait is safe. It does not show the stall is gone: none occurred during this window, and it is not something the tests can fix.
  • Harness checks:
    • a stale delivery is skipped;
    • the lookup reports a delivered request (1 CLI event, SUCCESSFUL, 1 attempt), a request with no listener (0 events, 1 ignored), and an unknown id (no request);
    • negative control for the search filter: the real id matches 1 request and 1 event, a bogus id matches 0;
    • the debug output printed on failure contains no credentials.

🤖 Generated with Claude Code

…elivery failing later steps

The binary-body listen tests failed intermittently with "Connected. Waiting
for events..." then "no request reached the local app within 45s", which
could not say where the event went.

Reproduced locally: the event was created for the listening CLI and stayed
QUEUED with no delivery attempt for minutes while the CLI's websocket was
connected and answering pings. The same stall failed the JSON forwarding
test, so it is neither binary-specific nor in the CLI. The harness made it
worse: localApp.next took whatever arrived next, so a late delivery failed
the following steps with a wrong Content-Type and file.

- Wait for listen's "Connected. Waiting for events..." line instead of
  sleeping 12 seconds.
- Tag each send with X-Acceptance-Delivery-Id; each step waits for its own
  delivery and skips others.
- On timeout, look the request and its events up by that header and report
  event status and attempts, plus the websocket lines from listen's debug log.
- Drop the duplicate connection delete that logged a 410 warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@leggetter
leggetter marked this pull request as ready for review November 2, 2026 16:46
@leggetter
leggetter merged commit 6a43726 into main Nov 2, 2026
13 checks passed
@leggetter
leggetter deleted the fix/listen-binary-test-flake branch November 2, 2026 17:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant