t4mer@notebook

// article · http · laravel · 18 june 2026 · 2 min

HTTP 421 and the Host header I should not have set

The endpoint was fine. The payload was fine. One header was not.

Yesterday I had an API request that worked perfectly in Postman and failed from Laravel with HTTP 421.

The endpoint was correct. The payload was correct. The authentication was correct.

The problem was one HTTP header I should not have been setting manually.

What I thought 421 meant

I do not look at 421 often enough to have muscle memory for it. My first instinct, after a decade of Laravel, was to look at routes, middleware, and APP_URL. The application logs were calm. PHP-FPM had nothing interesting to say.

That silence is usually the hint. Laravel cannot explain a status code it never emitted.

Two different 421 stories

I have now seen 421 in more than one costume:

  1. TLS / HTTP/2 reuse - a connection opened for one hostname reused for another that the certificate or server block cannot serve. Browsers with a warm pool fail; curl on HTTP/1.1 looks fine.
  2. A Host header you supplied - Guzzle/Laravel HTTP client sending Host that does not match the URL you think you called. The proxy or origin then refuses the combination of connection and authority.

The first one is an Nginx/TLS problem. The second is an HTTP client problem wearing an infrastructure costume. I wasted time treating them as the same afternoon.

The investigation that was not linear

I did not go straight to the header.

I checked the Laravel route. It existed. I checked APP_URL. Fine. I restarted PHP-FPM because that is what you do when you do not yet have a theory. I compared staging and production nginx until they blurred. I blamed a deploy that had not touched Nginx.

Then I dumped the raw outbound request. The Host value was not the host of the URL. Once that was visible, 421 stopped being mystical.

The TLS version of this story still exists - see the Problem Log entry. Both belong in the same drawer: 421 is about authority and connection, not about your JSON.

What I check first now

  1. Did the application even see the request?
  2. What is the actual Host on the wire?
  3. HTTP/1.1 vs HTTP/2 - do the clients agree?
  4. Only then: certificates, server blocks, Laravel.

I expected a normal API response. I got 421. Time wasted: enough. Cause: a header I had no business setting, or a connection I had no business reusing. Lesson: when HTTP behaves strangely, inspect the actual request before blaming the framework.