How HTTP Works

Response header · deprecated

< Warning: 110 - "Response is Stale"

Warning Header

Learn about the deprecated Warning header that provided additional status information about message transformations. Understand why it was removed from HTTP.

Reviewed 4 min readadvanced3 sourcesTry itMarkdown
Direction
Response
Category
Caching
Spec
RFC 7234 §5.5 (obsolete)
Status
Deprecated: Obsoleted by RFC 9111; do not send
On this page

TL;DR: Warning is obsolete. RFC 9111 dropped it, so stop generating it and use Cache-Control, Age, and Cache-Status instead. If you see it in old logs, Warning: 110 meant a cache served a stale response, and 214 meant a proxy transformed the body.

What is Warning?

Warning carried information the status code couldn’t, such as a cache serving stale content or a proxy transforming the body. RFC 9111 §5.5 obsoletes it. If you see it in a response today, it comes from legacy software or an application-specific convention; current HTTP caching doesn’t require it.

Historical Usage

Headers and output on this page are examples. A typical legacy response:

Cache-Control: max-age=60
Age: 90
Warning: 110 cache.example.com "Response is Stale"

The response is 30 seconds past its freshness lifetime, and the warning just says so; it never gave the cache permission to serve stale. Current caches follow the rules in RFC 9111 §4, including applicable directives and validation requirements.

Whether a cache serves stale or fails the request depends on its stale-serving policy and the response’s directives. Warning never decided that. A response with Cache-Control: no-cache, for example, still needed validation before reuse, and adding Warning: 110 couldn’t change that. When you remove a Warning generator, review the cache’s reuse policy as a separate task.

Successful validation could strip an old 110 while keeping the same stored body. A transformation warning such as 214 followed different rules and could stick around. In archived traces, compare the response before and after validation; warnings weren’t always removed together, and a changed warning didn’t always mean a new body.

Syntax

The historical syntax, for reading old logs:

Warning: warn-code warn-agent "warn-text" ["warn-date"]

The code was three digits. The agent named the sender, or a pseudonym for it. The text was quoted. An optional quoted HTTP date, if present, had to match the response’s Date.

Here’s one with a matching date:

Date: Mon, 05 Oct 2026 10:00:00 GMT
Warning: 199 proxy.example.com "Miscellaneous Warning" "Mon, 05 Oct 2026 10:00:00 GMT"

Warning Codes

The MDN legacy reference records these meanings:

  • 110: stale response.
  • 111: attempted revalidation failed.
  • 112: disconnected operation.
  • 113: both heuristic freshness lifetime and response age greater than 24 hours.
  • 199: miscellaneous warning.
  • 214: transformation applied.
  • 299: miscellaneous persistent warning.

These are Warning codes, not HTTP status codes. 1xx warnings were removed after successful validation; 2xx warnings could stay.

Why It Was Deprecated

According to RFC 9111, few implementations generated it, even fewer showed it to users, and the heuristic-expiration problem it was partly designed for went away. The RFC never says the implementations were broken; the header just wasn’t earning its keep. Current HTTP has no requirement to flag stale reuse.

Modern Alternatives

Cache-Control controls reuse, and Age tells you how old a response is. Between them they cover most of what 110 and 113 used to say, though not every old code.

For cache diagnostics, RFC 9211 defines Cache-Status:

Cache-Status: edge; hit

It reports what the cache did, not an application error. Vendor headers such as X-Cache each have their own meanings. No standard maps Warning codes one-to-one onto custom headers or Server-Timing.

Legacy Support

Before removing a Warning generator, check whether any client actually reads it. You don’t need to implement the old code lifecycle for current HTTP caching; it’s obsolete. Keep cache policy and application error reporting as separate concerns.

If a legacy origin sends Warning and you’ve confirmed nothing reads it, nginx can strip it in your existing proxy location:

location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_hide_header Warning;
}

proxy_hide_header only hides fields coming from the upstream. Freshness and stale serving stay as they were, and a cache further downstream may add its own Warning. Compare a direct origin request with one through nginx to see which component is still sending it.

If your application needs to report partial results, put that in the response body. A JSON API might return a warnings array alongside its result. That array is your own contract, not the old HTTP field, so document what each code means and how clients should handle missing data. Copying the old three-digit codes into a new field without defining what they mean isn’t a migration.

Testing (for Legacy Systems)

Test with GET; a HEAD request may take a different cache path:

curl -sS -D - -o /dev/null https://example.com/resource

Record Warning, Date, Age, and Cache-Control together. A missing Warning tells you nothing about freshness or failed validation, since current caches aren’t expected to send it.

For an origin reachable locally behind a public proxy, compare the two paths:

curl -sS -D /tmp/origin.headers -o /dev/null \
  http://127.0.0.1:3000/resource
curl -sS -D /tmp/edge.headers -o /dev/null \
  https://example.com/resource

Send the same Host and authentication on both requests if your deployment needs them. A Warning that appears only at the edge tells you something downstream of the origin adds it, though you’ll still need to find out which component. Keep the raw values: multiple warnings and quoted dates trip up a naive split or regex.

In an old log, 214 meant something transformed the body. It says nothing about bytes saved or latency. 111 meant revalidation failed, and it’s not the origin’s final HTTP status. Check the accompanying status, validators, and proxy error logs before blaming either code on a specific backend failure.

Frequently asked questions

What is the Warning header?

Warning was a response header that flagged things the status code could not, such as a cache serving stale content or a proxy transforming the body. RFC 9111 made it obsolete, so new code should stop sending it.

Why was Warning deprecated?

RFC 9111 says Warning was rarely generated or surfaced to users, and its heuristic-expiration motivation became unnecessary.

What were common Warning codes?

Legacy codes included 110 for stale responses, 111 for failed revalidation, 112 for disconnected operation, and 113 when both heuristic freshness lifetime and response age exceeded 24 hours.

What should I use instead of Warning?

Use Cache-Control to control reuse, Age to see how old a response is, and Cache-Status to report what a cache did with it. No single standard header maps one-to-one onto every old Warning code.

Sources

  1. MDN Web Docs: Warningdeveloper.mozilla.org
  2. RFC 9111: Warning (Obsoleted)rfc-editor.org
  3. RFC 9211: Cache-Statusrfc-editor.org

Keep going

Browse /search