417 Expectation Failed: Drop the Expect Header
417 Expectation Failed means a proxy rejected your Expect: 100-continue. Resend without the header, find where the 417 starts. Free instant check, no sign-up.
Check your domain for this issue now
Free, no sign-up. Runs the exact check this guide describes and shows what to fix.
Problem
You send a POST or PUT with a decent-sized body, and instead of the response you expect, you get 417 Expectation Failed. The body is fine. The endpoint works from a browser. But your client — curl, a library, a scripted upload — keeps getting bounced. The server isn’t objecting to what you sent. It’s objecting to a question your client asked before sending it.
Symptoms
- A
POST/PUT/PATCHreturns 417 immediately, with no application-level error body. - It only happens on larger requests — small ones with the same endpoint work fine.
- The failing requests carry an
Expect: 100-continueheader. - The same call works with a browser or a different HTTP client, but fails from curl or a specific library.
- It started after a new proxy, load balancer, or corporate network appeared in the path.
What This Error Actually Means
HTTP/1.1 has a politeness mechanism for large uploads. Before streaming a big body across the network, a client can send its headers plus Expect: 100-continue and wait. The server looks at the headers — the auth, the content type, the declared size — and answers 100 Continue if it’s willing to accept the body, or a final status (like 401 or 413) if it’s going to reject it anyway. The client saves itself from pushing megabytes at a server that was only ever going to say no.
100-continue is the only expectation the standard ever defined. And 417 is what you get when the chain can’t honor it. RFC 9110 §15.5.18 is precise: 417 means the expectation “could not be met by at least one of the inbound servers.” Not the origin, necessarily — at least one server in the path. The usual offender is an HTTP/1.0 hop that predates the whole mechanism. It sees a header it doesn’t understand, and rather than ignore it, it rejects the request outright.
The important word is inbound. Your body never reached the application. The request died at the handshake, on the Expect header alone, somewhere between your client and the server. The RFC also hands you the cure directly: a client that gets a 417 “SHOULD repeat that request without a 100-continue expectation.” Drop the header, resend, and the identical body goes through — because there was never anything wrong with the body.
Top 3 Causes
- A legacy HTTP/1.0 proxy or load balancer in the path. This is the textbook cause.
Expect: 100-continueis an HTTP/1.1 feature; an HTTP/1.0 intermediary that doesn’t implement expectations is supposed to ignore the header, but plenty of older middleboxes reject the request with 417 instead. The tell: it works direct-to-origin and fails only when the request transits a particular proxy or corporate network. - Your client auto-adds
Expect: 100-continueand something upstream hates it. Many HTTP clients add the header for you once the body is large enough — libcurl does it for bodies over about 1024 bytes. You never asked for the handshake; the library did. If any hop in front of the server can’t do the dance, every large upload 417s while small ones succeed, because only the large ones triggered the header. - A strict server or WAF configured to refuse expectations. Some origins and web application firewalls are set to reject
Expect: 100-continueoutright rather than answer it — sometimes deliberately, sometimes as a side effect of an old configuration. The request is well-formed; the policy simply won’t play the100-continuegame, and 417 is how it says so.
Diagnose with DechoNet
- HTTP Check confirms the endpoint itself responds cleanly to a normal request — no
Expectheader involved. If the tool gets a healthy response while your client gets 417, you’ve isolated the problem to the expectation, not the server or the payload. - The check surfaces the response headers and any intermediary fingerprints (
Via,Server, proxy signatures). A 417 that appears only behind a specific edge points squarely at a middlebox in the path — the thing to fix or route around — rather than your code.
Resolution Checklist
- Confirm it’s really 417, not a 400 (malformed request) or a 413 (body too large). Only 417 is about the
Expectheader, and only 417 is solved by removing something rather than reshaping the request. - Resend without the expectation. In curl, add
-H "Expect:"(an empty value) to strip the header entirely. The same body then uploads in one shot. - Turn off auto-expect in your HTTP library. Most clients have a setting to disable the automatic
Expect: 100-continueon large bodies — flip it, or send an emptyExpectheader yourself. - Find the offending hop. If it only fails through a proxy, load balancer, or corporate network, that intermediary is the one rejecting expectations. Test direct-to-origin to prove it, then fix or bypass the middlebox.
- If you run the server or WAF, check whether it’s configured to reject
Expectheaders, and decide whether to answer100 Continueinstead of bouncing the request. - Re-test through the same path. Verify the fix against the real network route, not just a clean direct call — the whole point is that the failure lived in the path.
When to Escalate
- If you’ve stripped the
Expectheader and still get 417, escalate to whoever runs the proxy, load balancer, or WAF in front of the service — a middlebox may be injecting its own expectation, or rewriting the request in a way only its logs will reveal. - If a third-party API returns 417 for a documented upload that you’re sending correctly, flag it to them: a 417 on an endpoint that advertises large uploads usually means a broken HTTP/1.0 hop on their side, and only they can fix the intermediary.
Related Tools
Related Guides
Share this guide