Outbound HTTPS uploads to api.openai.com failing with "Premature close" from my service
gnutttggg
FREEOP

6 days ago

My service (project: ghi-server, service: ghi-server, region: US West) cannot complete outbound multipart POST requests to https://api.openai.com/v1/audio/transcriptions. They fail at the network layer with:

Invalid response body while trying to fetch https://api.openai.com/v1/audio/transcriptions: Premature close

Key details that point to an egress/network issue rather than my code:

Small outbound requests from the same container succeed (e.g. requests to Google's generativelanguage.googleapis.com work fine at the same time). It's specifically the larger multipart upload to OpenAI's audio endpoint that drops.

The exact same request, with the exact same audio and API key, succeeds from my local machine — only the deployed Railway container fails.

The failure is persistent (hours), and survived multiple redeploys, a service restart, and a region change — so it's not a one-off container/IP fluke.

No relevant OpenAI or Railway status incident is posted.

Runtime is Node.js (currently Node 24, using global fetch/undici for the upload).

Could you check for an egress routing / MTU / NAT or IP-reputation issue on the path from my service's host to api.openai.com, and whether my service's outbound IP may be rate-limited or blocked by OpenAI? Happy to run any diagnostic command inside the container if useful.

$10 Bounty

7 Replies

Railway
BOT

6 days ago

This thread has been opened as a bounty so the community can help solve it.

Status changed to Open Railway 6 days ago


stewiezgaming-web
HOBBYTop 10% Contributor

4 days ago

Only community members can answer here until staff picks it up, so here's how I'd isolate it — your evidence (small requests fine, large multipart drops, local works) fits three candidate causes, and each has a distinct test:

Rule undici in/out first. SSH into the container (railway ssh) and send the same audio file with curl:

curl -v --http1.1 -F file=@test.mp3 -F model=whisper-1 https://api.openai.com/v1/audio/transcriptions -H "Authorization: Bearer $OPENAI_API_KEY"

If curl succeeds where fetch fails, this is a Node/undici issue, not Railway egress. Node 24's undici has known issues with large streaming multipart bodies over reused keep-alive connections — try the official openai SDK, or give fetch a fresh dispatcher with keep-alive disabled:

jsimport { Agent } from "undici";

fetch(url, { dispatcher: new Agent({ pipelining: 0 }), ... })

Buffering the file fully into a Blob before sending (instead of streaming) is another quick test.

If curl also fails, it's genuinely a path/NAT issue. Try enabling Static Outbound IPs (Service → Settings → Networking → Enable Static IPs, docs) — that moves your egress off the shared per-host NAT onto dedicated gateway IPs, which sidesteps both per-host connectivity drops and IP-reputation throttling of shared egress IPs by OpenAI.

If it's intermittent by host, note there's an actively investigated intermittent outbound-connectivity issue on shared egress (see the "[URGENT PROD DOWN] Networking / Outbound Connection Problems" thread where staff confirmed it) — a redeploy moves you to a fresh host, and static egress is the recommended mitigation there too.

If you post the curl result from inside the container, that'll pin down which bucket you're in.


This is a known nodejs issue, pin the node version to 24.18.0 or newer for the fix


stewiezgaming-web
HOBBYTop 10% Contributor

4 days ago

Confirming mayoriii's answer with the specifics, since this pins down which bucket you're in without needing the curl test:

Node 24.17.0 was a security release (CVE-2026-48931, "response queue poisoning in http.Agent") that added a guard on idle keep-alive sockets. That guard makes some HTTP clients treat a reused pooled socket as prematurely closed — which is exactly your error. Fixed in 24.18.0 via nodejs/node#64004; tracking issue is nodejs/node#63989.

Two details worth knowing:

The error string Invalid response body while trying to fetch ... Premature close is node-fetch@2's format, not undici's. So even though you're calling global fetch, something in your dependency tree (an SDK dep or polyfill) is routing this request through node-fetch@2 + a keep-alive http.Agent — that's the exact code path the regression breaks.

This explains every symptom you listed: works locally (different Node patch version), survives redeploys and region changes (the runtime version ships with your image), and small requests succeed while the large multipart upload fails (the bug triggers on reused pooled sockets under load). No Railway egress/NAT/IP-reputation issue involved.

Fix: if you're on a floating node:24 base image (or a Nixpacks/Railpack default that resolved to 24.17.0), pin Node to 24.18.0 or newer and redeploy. node --version inside the container will confirm whether you were on 24.17.0.


lleywyn
PROTop 5% Contributor

4 days ago

answered - disregard


vicenteostornol
HOBBY

3 days ago

You're the best engineer in the entire world, keep it up!


stewiezgaming-web

Confirming mayoriii's answer with the specifics, since this pins down which bucket you're in without needing the curl test: Node 24.17.0 was a security release (CVE-2026-48931, "response queue poisoning in http.Agent") that added a guard on idle keep-alive sockets. That guard makes some HTTP clients treat a reused pooled socket as prematurely closed — which is exactly your error. Fixed in 24.18.0 via nodejs/node#64004; tracking issue is nodejs/node#63989. Two details worth knowing: The error string Invalid response body while trying to fetch ... Premature close is node-fetch@2's format, not undici's. So even though you're calling global fetch, something in your dependency tree (an SDK dep or polyfill) is routing this request through node-fetch@2 + a keep-alive http.Agent — that's the exact code path the regression breaks. This explains every symptom you listed: works locally (different Node patch version), survives redeploys and region changes (the runtime version ships with your image), and small requests succeed while the large multipart upload fails (the bug triggers on reused pooled sockets under load). No Railway egress/NAT/IP-reputation issue involved. Fix: if you're on a floating node:24 base image (or a Nixpacks/Railpack default that resolved to 24.17.0), pin Node to 24.18.0 or newer and redeploy. node --version inside the container will confirm whether you were on 24.17.0.

matistat3
FREE

3 days ago

Thanks you!! Our two users are too grateful


matistat3

Thanks you!! Our two users are too grateful

vicenteostornol
HOBBY

3 days ago

i confirm, im one of those users.


Welcome!

Sign in to your Railway account to join the conversation.

Loading...