console: the gateway proxy waits as long as it declares, not undici's five minutes - #214
Open
sakurahello1 wants to merge 1 commit into
Open
sakurahello1 wants to merge 1 commit into
sakurahello1 wants to merge 1 commit into
Conversation
… five minutes The BFF's maxDuration says 800 s, but the fetch it makes to the gateway was bounded by undici's defaults: 300 s for the response headers and 300 s between body chunks, then "fetch failed". A synchronous POST /v1/responses sends nothing until the turn ends, so a turn longer than five minutes came back 502 "harness-gateway unreachable" while the runner finished it — 301.0 s and 300.3 s on turns the session store shows completing at 340 s and 354 s — and a streamed turn silent for five minutes inside one tool call would end the same way. The gateway's own hop to the runner reads for an hour on purpose. The proxy now dispatches through an undici Agent whose headers and body timeouts are maxDuration. Measured on the built console against a stub gateway that answers after 305 s: before, 502 "fetch failed" at 307.8 s; after, 200 at 305.0 s. undici 6.x is the line Node 22 carries itself, so the Agent speaks the interface the built-in fetch calls.
|
@sakurahello1 is attempting to deploy a commit to the Future HR Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
🟢 Approval recommended
The timeout alignment and dependency updates have no unresolved blocking issues.
Pull request overview
Updates the Harness Gateway proxy to honor its declared 800-second duration instead of Undici’s five-minute defaults.
Changes:
- Configures extended header and body timeouts through an Undici
Agent. - Adds and locks the
undicidependency.
File summaries
| File | Description |
|---|---|
ui/src/app/api/harness/[...path]/route.ts |
Applies extended upstream timeouts. |
ui/package.json |
Adds the undici dependency. |
ui/package-lock.json |
Locks the dependency and integrity data. |
Review details
Files not reviewed (1)
- ui/package-lock.json: Generated file
- Files reviewed: 2/3 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
ui/src/app/api/harness/[...path]/route.tsdeclaresmaxDuration = 800, but thefetchit makes to the gateway was bounded by undici's defaults instead: 300 s for the response headers and 300 s between body chunks, thenfetch failed, which the route turns into502 harness-gateway unreachable. A synchronousPOST /v1/responsessends nothing until the turn ends, so every turn longer than five minutes came back 502 through the console's API path while the runner finished it; a streamed turn silent for five minutes inside one tool call would end the same way. The gateway's own hop to the runner reads for an hour on purpose (httpx.Timeout(read=3600), "a long agent turn … never be cut off"), so this hop was the only one with a five-minute ceiling, and it was not a chosen one.The proxy now dispatches through an undici
AgentwhoseheadersTimeoutandbodyTimeoutaremaxDuration— one number, the one the route already declares.How this showed up
Running a task slice through a self-hosted CE (0.18.x) over
http://localhost:3000/api/harness: 4 of 20 synchronous turns came back502 {"detail":"harness-gateway unreachable: fetch failed"}at 301.0 s, 300.3 s, and twice more, whileGET /v1/sessionsshowed the same sessionsdoneat 340 s, 354 s, 444 s and 425 s with their files and usage stored. The client had to find the session by hand to grade the turn.Measured
Node 22's fetch against a stub that answers after 305 s:
fetch failed | cause: UND_ERR_HEADERS_TIMEOUT Headers Timeout Errorat 300.8 s.The built console (standalone output) proxying to a stub gateway that answers after 305 s, same machine, same request:
{"detail":"harness-gateway unreachable: fetch failed"}HTTP 502 at 307.8 s{"ok":true}HTTP 200 at 305.0 sNotes
undici^6.28.1is added to the console's dependencies: the 6.x line is what Node 22 carries itself (the image's Node 22.23.2 reports undici 6.28.0), so the Agent speaks the dispatch interface the built-in fetch calls; Node 20 in CI is inside 6.x's support range. Webpack bundles it into the route chunk, so the standalone output needs no extra tracing.(init as RequestInit & { duplex: 'half' }).duplex = 'half'cast no longer type-checks onceinitcarriesdispatcher;duplexmoved intoinit's declared type. No behaviour change there.tests.yml's note), and the first test file brings the jest configuration with it, which is not this change.npm run type-checkandnpm run buildpass.