next is intermittently red: TestGetStopsWaitingWhenCanceled gets the 503 instead of the deadline when a request outlasts it #221

Closed
opened 2026-10-14 00:26:08 +02:00 by clawbot · 1 comment
Collaborator

TestGetStopsWaitingWhenCanceled in internal/cli/fetch_test.go fails now and then on a loaded host, so next (7542a68) is intermittently red: Target error should be in err chain: expected: "context deadline exceeded" in chain: "unexpected HTTP status 503".

The test gives retryingClient.get (in internal/cli/fetch.go) a 50 ms deadline against a server that always answers 503, and expects the deadline error. get checks ctx.Err() != nil right after a request and then returns that request's error. When the request itself takes longer than 50 ms, as it can under load, the deadline has passed by the time the 503 arrives, and get returns the 503 rather than the cancellation. So the result depends on timing: a fetch that runs out of time while a request is in flight reports the server's status, while one that runs out during the wait between retries reports the deadline.

Severity: critical. next fails on it intermittently.

Correct: when get stops because its context is done, it returns an error that wraps the context's error, keeping the last attempt's error with it, whether the context ended during a request or during the wait. The test then passes whatever the timing.

Definition of done

  • A test that fails today whatever the host's load: the context ends while the first request is in flight (for example, a server that answers 503 only after the deadline has passed), and get returns an error that wraps context.DeadlineExceeded and the 503.
  • The fix in retryingClient.get.
  • make test passes several times in a row on a loaded host.
  • make check passes.

Model: opus-5-5

`TestGetStopsWaitingWhenCanceled` in `internal/cli/fetch_test.go` fails now and then on a loaded host, so `next` (7542a68) is intermittently red: `Target error should be in err chain: expected: "context deadline exceeded" in chain: "unexpected HTTP status 503"`. The test gives `retryingClient.get` (in `internal/cli/fetch.go`) a 50 ms deadline against a server that always answers 503, and expects the deadline error. `get` checks `ctx.Err() != nil` right after a request and then returns that request's error. When the request itself takes longer than 50 ms, as it can under load, the deadline has passed by the time the 503 arrives, and `get` returns the 503 rather than the cancellation. So the result depends on timing: a fetch that runs out of time while a request is in flight reports the server's status, while one that runs out during the wait between retries reports the deadline. Severity: critical. `next` fails on it intermittently. Correct: when `get` stops because its context is done, it returns an error that wraps the context's error, keeping the last attempt's error with it, whether the context ended during a request or during the wait. The test then passes whatever the timing. ## Definition of done - A test that fails today whatever the host's load: the context ends while the first request is in flight (for example, a server that answers 503 only after the deadline has passed), and `get` returns an error that wraps `context.DeadlineExceeded` and the 503. - The fix in `retryingClient.get`. - `make test` passes several times in a row on a loaded host. - `make check` passes. Model: opus-5-5
clawbot self-assigned this 2026-10-14 00:26:08 +02:00
Author
Collaborator

Fix and test are in #222: when the context ends before a retry, get now returns an error wrapping both the context's error and the last try's error.

Model: opus-5-5

Fix and test are in https://git.eeqj.de/sneak/mfer/pulls/222: when the context ends before a retry, `get` now returns an error wrapping both the context's error and the last try's error. Model: opus-5-5
Sign in to join this conversation.