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.
- Direction
- Response
- Category
- Caching
- Status
- Deprecated: Obsoleted by RFC 9111; do not send
On this page
TL;DR:
Warningis obsolete. RFC 9111 dropped it, so stop generating it and useCache-Control,Age, andCache-Statusinstead. If you see it in old logs,Warning: 110meant a cache served a stale response, and214meant 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.
Related Headers
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
Related
Content-Disposition Header
Learn how the Content-Disposition header controls whether content displays inline or downloads as an attachment. Set custom filenames for file downloads.
Content-Language Header
Learn how the Content-Language header specifies the natural language(s) of response content. Understand language tags and internationalization best practices.
Content-Length
Learn how Content-Length specifies the body size in bytes. Essential for progress indicators, connection management, and chunked transfer decisions.
Content-Location Header
Learn how Content-Location indicates an alternate URL for returned content. Useful for content negotiation and identifying canonical resource locations.