HTTP 417 Expectation Failed

Expectation Failed

HTTP 417 is Expectation Failed: at least one server on the request’s path couldn’t meet the expectation in its Expect header (RFC 9110 section 15.5.18). The only expectation HTTP defines is 100-continue (section 10.1.1), and a server that receives any other may answer 417.

Where it comes from

  • An unknown expectation. Node’s http server answers 417 to any Expect other than 100-continue unless you handle the checkExpectation event. Go’s server answers 417 to one too, with no hook to change it.
  • 100-continue through an old intermediary. An HTTP/1.0 proxy can’t send a 100 response. RFC 9110 says a 417 to a 100-continue merely shows that the chain doesn’t support expectations, for example because it passes through an HTTP/1.0 server.
  • .NET Framework’s HttpWebRequest sends Expect: 100-continue on POSTs by default, so behind such a proxy it fails with The remote server returned an error: (417) Expectation Failed.

What the client should do

RFC 9110 says a client that gets a 417 in response to 100-continue should repeat the request without the expectation. Most clients have a switch for it:

curl -H 'Expect:' -T backup.tar https://example.com/uploads/
ServicePointManager.Expect100Continue = false;        // .NET Framework, before the first request
request.Headers.ExpectContinue = false;               // HttpClient

Dropping Expect costs little: the client just sends the body without waiting for permission, which is what it would do after a timeout anyway.

Sending it

Node answers unknown expectations itself; handle the event when you want a body that says what went wrong:

server.on('checkExpectation', (req, res) => {
  res.writeHead(417, { 'Content-Type': 'text/plain' });
  res.end('Only "Expect: 100-continue" is supported.\n');
});

Gotchas

  • Not a validation error. A body that fails your rules is a 400 or a 422; 417 is only about the Expect header.
  • One retry, not a loop. A client that keeps sending Expect after a 417 will keep getting it.
  • Caching. 417 isn’t heuristically cacheable.

Search 100 417 in the tool below to compare the two.

Try it in the HTTP Status Codes

417 Expectation Failed

  1. 417Expectation Failed4xx Client error

    The server cannot meet the expectation in the Expect header, which in practice means it will not do the 100-continue dance.

    When to use it

    Rare: an intermediary that cannot handle an expected handshake says so instead of hanging.

    Common mistakes

    Sending it as a general validation failure, which is what 400 and 422 are for.

    Not cacheable by defaultRFC 9110

Every code, by class

Codes marked unofficial come from one server’s own convention — nginx, Cloudflare, cPanel, Microsoft — and are not in the IANA registry.

Runs in your browser. Nothing you enter is sent anywhere.