Conversation
…t configurable Both proxies forwarded inference requests over a transport with ResponseHeaderTimeout 120s. That timer runs until the FIRST response header byte, and a non-streaming completion sends none until the whole answer is generated, so any non-streaming request that queued behind other jobs or ran a long reasoning model failed after exactly 120s with "upstream error: net/http: timeout awaiting response headers", the job was marked failed, and the engine's work was discarded. A request to a PAIR peer crossed two hops (router -> peer ingress -> engine) that each applied it. The default becomes 30 minutes and is overridable per install with --response-header-timeout or NVPAIR_PROXY_RESPONSE_HEADER_TIMEOUT (flag > env > default, like --log-level; 0 waits indefinitely). The proxies inherit the broker's environment, so the variable reaches them on desktop and headless installs without a spawn change. Unreachable hosts are still cut off by the 10s dial timeout, dead clients by idleClientWriteTimeout, and a client that gives up cancels the upstream request through its context; the deadline remains only as a backstop for an engine that accepted the connection and never answers. Model-list fetches keep their 10s limit. New nvpair-shared/envflag provides the duration flag/env resolver. Tests cover the precedence rules, that the value reaches every transport (and 0 disables it), and that a silent upstream fails past a short deadline and succeeds under a long one. Bumps ollama-proxy 0.27.0, lmstudio-proxy 0.17.0, product 0.92.0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Can GULDOGAN <cguldogan@gmail.com>
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.
Description
ollama-proxyandlmstudio-proxyforward inference requests over anhttp.TransportwithResponseHeaderTimeout: 120s. That timer runs from the moment the request is sent until the first response header byte. A streaming completion sends headers immediately, so it never notices. A non-streaming completion sends nothing until the whole answer is generated, so the timer covers queue wait + prefill + the entire generation — and any non-streaming request that queues behind other jobs, or runs a reasoning model, fails after exactly 120 s:The job is marked failed and the engine's work up to that point is discarded. A request to a PAIR peer crosses two hops (router → peer's mTLS ingress → engine), and each hop applied the same 120 s independently.
Every SDK call without
stream: trueis non-streaming — the OpenAI SDK's defaultchat.completions.create(...), most eval and batch scripts. Their own default timeouts are 600 s (OpenAI SDK, LiteLLM); PAIR was cutting off at 120.Change: the default becomes 30 minutes, and it is configurable per install:
--response-header-timeout <duration>on both proxies, orNVPAIR_PROXY_RESPONSE_HEADER_TIMEOUTin the environment (the proxies inherit the broker's environment, so this reaches them on desktop and headless installs without a spawn change),with the same precedence as
--log-level(flag > env > default).0waits indefinitely. Unreachable hosts are still cut off by the 10 s dial timeout, dead clients byidleClientWriteTimeout, and a client that gives up cancels the upstream request through its context, so the header deadline only remains as a backstop for an engine that accepted the connection and never answers. Model-list fetches keep their separate 10 s limit.Scope
services/shared/envflag: new small package — a duration flag whose default comes from anNVPAIR_*env var, mirroringapplog.RegisterFlag.defaultResponseHeaderTimeout(30 m), aresponseHeaderTimeoutfield onProxythreaded intonewProxyTransport(plain, manual and mTLS peer transports alike), the flag/env wiring inmain.go, and the startup "proxy timeouts configured" log line reporting the effective value.services/readme.md(new "Inference timeouts" section).services/versions.json: MINOR bump forollama-proxy(0.26.2 → 0.27.0) andlmstudio-proxy(0.16.2 → 0.17.0) — each gains a new flag and a changed default a--versionreader would want to know about; product/installer 0.91.7 → 0.92.0 per VERSIONING.md (at least one MINOR component bump, user-visible behaviour change).Validation
cd services/shared && go test ./envflag/— precedence (flag > env > default),0, and error messages that name their origin (--flagvs$ENV).cd services/lmstudio-proxy && go test ./...and the same inollama-proxy— newresponse_header_timeout_test.goin each:0disables the deadline;httptestupstream (500 ms before headers) yields 502 with a shorter deadline and 200 with a longer one or0— i.e. the deadline is really applied end to end throughhandleHTTP.go test -raceon both proxies;go veton all three modules;make headers,make contractsclean.cd services/tests && go test ./...(cross-process suite): pass, no skips, with the desktop app stopped and an isolatedHOME.--helpshows the flag with(default: $NVPAIR_PROXY_RESPONSE_HEADER_TIMEOUT or 30m0s);NVPAIR_PROXY_RESPONSE_HEADER_TIMEOUT=bogusexits with$NVPAIR_PROXY_RESPONSE_HEADER_TIMEOUT: "bogus" is not a duration (use e.g. "30m", "90s" or "0").ollama-proxy'sTestAliasSelfTargetMatchesBoundLoopbackAddressNotPortAlonefails on a stock macOS host because it binds127.0.0.2, which is not aliased on loopback by default; it fails identically on an untouched checkout of the base.Verification ceiling: the first hop is unit-tested as above. That the peer's ingress hop applies the same deadline is read from
ingress.go(newLocalReverseProxy→plainHTTPTransport()), not measured end to end across two machines.Risk
NVPAIR_PROXY_RESPONSE_HEADER_TIMEOUT.Checklist
git commit -s), certifying the Developer Certificate of Origin.services/versions.json, and described user-visible changes above so they reach the release notes.🤖 Generated with Claude Code