Skip to content

generator: default --timeout kills streaming/binary transfers mid-flight #3554

Description

@rvdlaar

Filed by /printing-press-retro from a run of GitHub Contents (scorecard 89/100, 94% verify pass, full live dogfood 99/99, printed with cli-printing-press v4.28.0).

Summary

The generated client/context wiring is tuned for JSON API calls: the global --timeout (default 1m) bounds the whole invocation, and ancillary HTTP clients use whole-body http.Client.Timeout. Any streaming/bulk transfer that outlives the default dies mid-flight. On this print's real target, a 1.92 GB / 118-file fetch got 64 files in ~60s, then every remaining and in-flight transfer failed with "context deadline exceeded".

Where to look

  • Component: generator
  • Likely area: client template (timeout wiring) + command emission for response_format: binary endpoints
  • Triggered when: any transfer where bytes × bandwidth > default timeout — binary endpoints, archive/asset downloads, hand-built bulk fetchers

What we observed

  • Observed failure above (proofs in the retro's acceptance report).
  • Fix pattern implemented + verified in the published print (printing-press-library PR bug(generator): promoted_test.go is excluded from go build, uncovered case for #1020 #1489, internal/cli/ghfetch_common.go): walk/API phase keeps the --timeout-bounded context; the transfer phase runs on an unbounded-but-cancellable context unless cmd.Flags().Changed("timeout") (explicit user choice still wins), and the streaming HTTP client uses ResponseHeaderTimeout: 30s with no whole-body cap (ghfetch.NewStreamingHTTPClient).
  • Subclass evidence: tenderned's spec has a response_format: binary endpoint (same generated client shape); scorer: dogfood json_fidelity fires on binary/non-JSON-response endpoints #2940 independently establishes binary/non-JSON endpoints as a class the scorer already trips on.

Suspected root cause

No streaming carve-out exists: one timeout default serves both JSON calls (where 1m is right) and bulk transfers (where it's fatal). Confidence: high on mechanism (reproduced + fixed); medium on where the template change lands cleanest (client template vs per-endpoint emission).

Suggested direction

For response_format: binary endpoints (guard: JSON endpoints unchanged): emit a streaming client (header timeout, no whole-body cap) and run the transfer on a context that applies --timeout only when explicitly set. The print-side implementation above can serve as the reference.

Acceptance criteria

  • positive: a binary-endpoint transfer larger than default-timeout×bandwidth completes; stalls are still caught by the header timeout
  • negative: explicit --timeout 5s still aborts a slow transfer; JSON endpoints keep the bounded default

Frequency

subclass:streaming-download (response_format: binary endpoints + documented bulk-download engines)

Complexity

medium

Related issues

Artifacts

Upload to catbox.moe failed ("Invalid uploader"). Scrubbed zips preserved locally in the printer's run proofs: manuscripts/github-contents/20260710-125244-1a986992/proofs/github-contents-{manuscripts,cli-source}.zip. Retro doc: same directory, 20260711-021500-retro-github-contents-pp-cli.md.


Generated by /printing-press-retro · CLI Printing Press

Metadata

Metadata

Assignees

No one assigned

    Labels

    comp:generatorpriority:P2retroResults from a Printing Press retrospective session which identifies improvements or fixes

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions