Skip to content

v3.25.3

Choose a tag to compare

@github-actions github-actions released this 30 Aug 09:56
· 11 commits to main since this release
  • API provider requests survive Node 26.0's built-in fetch (empty headers, still-gzipped body) (#91). Importing npm undici — which modlens resolves from node_modules since #23 — claims the process-wide undici.globalDispatcher.2 slot at load time. Node 26.0.0's built-in fetch is undici 8.0.2 and reads that same slot, so on the no-proxy path (which used the host fetch) it drove npm undici 8.10.0's Agent. The two disagree about HTTP/2 response headers: 8.0.2's fetch walks rawHeaders as a flat array while 8.10.0's h2 client hands over an object, so the walk runs zero times and every header is dropped — content-encoding included. The gzip body was never decompressed and response.json() threw Unexpected token '\x1f' on the raw bytes. Gemini's endpoint negotiates HTTP/2, which is why gemini-api surfaced it; HTTP/1.1 headers are already an array and are immune, as are Node 24 (built-in undici 7.x on the .1 slot, with h2 forced off by the compat wrapper) and Node 26.8+ (built-in 8.10.0 agrees with the npm copy). apiFetch now never touches the host fetch: with or without a proxy it uses npm undici's own fetch with a same-sourced dispatcher, verified by an integration test over the real undici stack and against a local HTTP/2 gzip server on Node 26.0.0. A body that fails mid-read after the response arrived keeps its status and headers readable and rejects text()/json() with the original error, so 401 classification and API key rotation are unchanged, and connect failures still raise the connectivity hint. Thanks to @Sol1l0quy for a report that had already isolated the failing layer with a fetch probe and byte-for-byte replays.