All POST requests failing with 400 "Bad Request" - GET works fine
yudiarnanda
FREEOP

a month ago

Service: dirtyline-manager-production

Current deployment: dc0e8436 (Active, freshly restarted)

Every POST request to any action route in this app fails instantly (~2-7ms) with a generic 400 Bad Request, thrown deep inside react-router's internals (singleFetchAction → handleSingleFetchRequest → requestHandler) before our application code ever executes — confirmed via explicit try/catch + console.error at the very top of our action handlers, which never fires.

GET requests to the same routes work completely normally (200 status, correct data, our authenticate.admin() logs appear as expected).

What we've ruled out:

  • App code / recent commits (reverted changes, same error persists)

  • Build failures (latest build succeeded, "image push" completed)

  • Browser cache/cookies (tested in Safari, Chrome incognito, cleared site data — same error every time)

  • Stale session tokens (tested submitting within 5 seconds of page load)

  • Database/session issues (Session table has valid data for dirtyline-studio.myshopify.com)

  • Container health (manually restarted, same error persists immediately after restart)

This is reproducible on every POST action across multiple different routes in the app (/app/import, /app/fonts/[handle]), suggesting an edge/proxy-level issue specifically affecting POST method handling for this service, not an application bug.

Could you check the edge/proxy logs for this service around 2026-08-31 18:09 GMT+7 for the POST request to /app/import.data?index... which returned 400 in 6.673ms?

Solved$10 Bounty

1 Replies

Railway
BOT

a month ago

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

Status changed to Open Railway • about 1 month ago


vagacerta2026
FREE

a month ago

The fact that the 400 error occurs instantly (~2–7ms) deep inside React Router / Remix’s singleFetchAction before your application code executes indicates that Remix's internal request parser is rejecting the incoming POST payload.

With Remix Single Fetch, POST requests require strict header validation (such as correct Content-Type, Origin, Host, or serialization format). If an edge proxy, load balancer, or reverse proxy alters these headers or strips the request body before it hits the Node process, Remix’s router immediately throws a 400 Bad Request.

Key Areas to Investigate & Fix:

Proxy & Host Headers Mismatch: If Railway's edge proxy or a custom domain setup is modifying Host, X-Forwarded-Host, or X-Forwarded-Proto headers, Remix may view the POST request as a potential CSRF vector or cross-site mismatch and reject it outright.

Inspect Request Payloads in DevTools: Open your browser's Network tab, trigger the failing POST action, and compare the exact headers (Content-Type, Origin, Referer, and custom Single Fetch headers) against a working local development environment.

Remix / React Router Single Fetch Serialization: Ensure your client-side and server-side bundles are fully synchronized. A mismatch in the single-fetch serialization protocol between what the browser builds and what the server expects will cause an instant rejection.

Railway Edge Logs: Regarding your timestamp check (18:09 GMT+7), if the request returned a 400 in under 7ms without hitting your try/catch, it means either the container's entrypoint/middleware blocked it or Railway's edge rejected the request format before routing it into the app instance. Checking the raw infrastructure/deploy logs in the Railway dashboard for that specific request ID will confirm whether the request ever touched the Node.js runtime or was dropped at the edge.


Status changed to Solved yudiarnanda • about 1 month ago


Welcome!

Sign in to your Railway account to join the conversation.

Loading...