Skip to content

Retry transient transport failures of read-only git network operations before failing a Pass #880

Closed

Description

@JacobStephens2

This was generated by AI during triage.

Problem

A single transient network failure in a read-only git command fails a whole Pass and sends a failure notification. On 2026-10-19 at 22:06 EDT, the scheduled Architect run (--plan-only) for Educational-Travel-Adventures/tourbot on dev.etadventures.com failed 7 seconds in, while selecting an Issue branch for #880:

Result:       review failed
Review:       failed
Cause:        git ls-remote --heads origin refs/heads/issue-880 refs/heads/issue-880-branch-* failed: error: RPC failed; curl 16 Error in the HTTP2 framing layer
fatal: expected flush after ref listing
Built with claude · default model · default effort (configured)
Host:         dev.etadventures.com
Took:         7s

The same ls-remote succeeded in 0.6s the next morning. The cron logs on that host show one more failure of the same kind (git ls-remote --heads origin refs/heads/master failed: ... Error in the HTTP2 framing layer). The host's git uses curl 7.76.1 with nghttp2 1.43.

#786 added bounded retries for transient gh reads (via check_read::is_transient), but git commands that talk to origin are not covered. The Git wrapper's retry loop retries only when a git lock is held (held_lock), so a transport failure is final on its first attempt.

Agent Brief

Category: enhancement
Summary: Retry transient transport failures of read-only git network operations (ls-remote, fetch) within a small bounded budget before failing a Pass.

Current behavior:
Read-only git commands against origin run through the Git wrapper. Its retry loop retries only when another process holds a git lock. Any other nonzero exit, including a dropped HTTP/2 stream, a connection reset or a GitHub 5xx, becomes the Pass's failure cause right away. Callers include Issue branch selection (the Reads::on_origin read in branch selection), Pickup's branch reservation check, Worktree ownership checks and the Git wrapper's remote-head probe, as well as fetches.

Desired behavior:

  • A read-only git network operation (ls-remote, fetch) that fails with a transient transport classification is retried with increasing delay within a small bounded budget (for example 3 attempts, well under a minute in total). If every attempt fails, the operation fails with the last attempt's cause, in the same shape as today.
  • The transient classification recognises git/curl transport failures, for example: RPC failed; curl <n> (e.g. 16, 18, 56), Error in the HTTP2 framing layer, expected flush after ref listing, early EOF, the remote end hung up unexpectedly, Connection reset, Connection timed out, Could not resolve host, The requested URL returned error: 5xx (and 429), and TLS read errors (SSL_read, gnutls_handshake).
  • Permanent failures fail on the first attempt: authentication failures (Authentication failed, could not read Username, 401/403), Repository not found, unknown refs or remotes, and any error not classified as transient.
  • Each retry writes a progress/log line naming the command and the cause, so recovered failures stay visible.
  • Command interruption cancels a pending retry wait promptly.
  • The existing lock-wait behavior is unchanged.

Key interfaces:

  • The Git wrapper's retried-output path: it gains a transient-transport retry for read-only network commands, alongside the existing held_lock retry.
  • A transport-failure classifier analogous to check_read::is_transient, matching on git's stderr.

Out of scope:

Acceptance criteria

  • With a fake git that fails ls-remote once with error: RPC failed; curl 16 Error in the HTTP2 framing layer / fatal: expected flush after ref listing and then succeeds, Issue branch selection returns the second attempt's result, and the Pass continues with no failure notification.
  • A fake fetch that fails once with a transient transport error and then succeeds is retried the same way.
  • A transient failure that persists through the whole budget fails within the budget, with the last attempt's git error as the cause.
  • Authentication failures, Repository not found and other non-transient errors fail on the first attempt, with no retry.
  • push is never retried by this mechanism. A test shows a push transport failure is attempted exactly once.
  • Each retry emits one log line naming the git command and the cause.
  • Interrupting the Command during a retry wait ends the wait promptly.
  • Existing lock-wait retry tests still pass.

Related

Activity

  1. added
    enhancementNew feature or request
    ready-for-agentFully specified, ready for an AFK agent
    in-progressA Claim: thirdshift has taken this issue
    and removed
    ready-for-agentFully specified, ready for an AFK agent
    on Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions