When must an HTTP server respond with 405 Method Not Allowed, what header is mandatory on that response, and how does it differ from 501 Not Implemented?
answer
- 405 = known target, unsupported method
- Allow header is MUST on 405
- 501 = server doesn't implement the method at all (5xx)
- Unknown path 404 vs wrong verb 405
- Missing OPTIONS handler → 405 breaks CORS preflight
basics
~20 s405 means the target resource exists but does not support the method used. RFC 9110 requires the response to include an Allow header listing the methods it does support, e.g. Allow: GET, HEAD, PUT. 501 means the server does not recognise or implement the method at all.
solid answer
~50 s**405 Method Not Allowed** applies when the request target is recognised but the **method is not supported by that resource** — a POST to a read-only collection, a DELETE on a resource that cannot be deleted. RFC 9110 makes the `Allow` header **mandatory** on a 405: it must list the methods the resource does support, e.g. `Allow: GET, HEAD, OPTIONS`. This is the same header `OPTIONS` returns, and it is the only machine-readable way for a client to recover. Frameworks that emit a bare 405 are non-conformant, and clients then have to guess. **501 Not Implemented** is server-wide: the method is unrecognised or unsupported by the server for *any* resource (an exotic verb, an unimplemented WebDAV method). 501 is a 5xx — the server is admitting a limitation — whereas 405 blames the request. Also distinguish **404**: an unknown path is 404, a known path with the wrong verb is 405. Many routers wrongly collapse the second into the first, which hides real client bugs.
code
http · 9 linesDELETE /api/audit-log/42 HTTP/1.1
Host: api.example.com
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, OPTIONS
Cache-Control: no-store
Content-Type: application/json
{"code":"METHOD_NOT_ALLOWED","allowed":["GET","HEAD","OPTIONS"]}go deeper
Say that 405 means the URL exists but the verb is not supported, and that the response must list the supported methods in Allow.
Add the 404-vs-405 distinction, the 501 contrast including its 5xx class, and the OPTIONS relationship.
Cover CORS preflight fallout, stale cached 405s when the Allow set changes, whether to advertise methods the caller cannot use, and 503 rather than 405 for temporary read-only mode.
Position it as gateway and router policy: consistent method-mismatch handling across services so client SDKs and observability can separate routing bugs from verb bugs.
## What 405 asserts RFC 9110 defines **405 Method Not Allowed** as: the method received in the request-line is **known by the origin server but not supported by the target resource**. Two conditions matter — the *target exists* (or at least the route is recognised) and the *method is understood* but disallowed here. Examples: `DELETE /api/audit-log/42` on an append-only log; `POST /api/reports/monthly` where only GET is offered; `PUT /api/orders` on a collection that only accepts POST. ## The mandatory Allow header The spec is unusually strict: the origin server **MUST** generate an `Allow` header field in a 405 response, containing a list of the target resource's currently supported methods. ``` HTTP/1.1 405 Method Not Allowed Allow: GET, HEAD, OPTIONS ``` Points worth knowing: - `Allow` is a **response** header describing the *resource*, not the server. The same server can return different `Allow` values for different paths. - An empty `Allow:` is legal and means the resource supports no methods at all — rare, but defined. - The same header is the core of an `OPTIONS` response, so `OPTIONS` and 405 are two sides of the same discovery mechanism. - Whether to advertise methods the caller is not authorised to use is a judgement call: `Allow` describes the resource, so listing DELETE for a read-only user is spec-legal, but some teams trim it to avoid advertising an attack surface. ## 405 versus 501 **501 Not Implemented** means the server does not support the **functionality required to fulfil the request** — in practice, it does not recognise or implement the method for any resource. It is the correct answer to a verb the server has never heard of, or to a standard method (say, `PATCH` or a WebDAV verb) the server has simply not built. Critical difference in class: **501 is 5xx**, so it counts as a server-side limitation, is cacheable by default, and will show up in server-error dashboards and SLOs. **405 is 4xx**, blaming the request. Choosing 501 for "this endpoint does not do DELETE" therefore both mislabels fault and pollutes your error-rate metrics. ## 405 versus 404 This trips people up constantly: - Unknown path → **404 Not Found**. - Known path, unsupported verb → **405 with Allow**. Some routers return 404 for both because they match on path+method as a single key and fall through to a catch-all. That is a real diagnostic loss: a client sending `POST` where the API wants `PUT` sees "endpoint missing" and the developer chases the wrong bug. Most modern frameworks can distinguish path-match-with-method-mismatch; enabling that is a small, high-value fix. A related quirk: whether `HEAD` is allowed. RFC 9110 says a server supporting GET must also support HEAD, so a resource that lists `GET` in `Allow` should list `HEAD` too, and returning 405 to a HEAD on a GETable resource is a bug. ## Where 405 shows up in the wild - **CORS preflights**: a browser sends `OPTIONS` before a cross-origin PUT. If the framework has no OPTIONS handler, it answers 405 and the preflight fails, which surfaces to the developer as a confusing CORS error rather than a method error. Ensuring `OPTIONS` is handled on every route is standard hygiene. - **Static file servers and CDNs**: usually only GET/HEAD; a POST returns 405, sometimes with `Allow: GET, HEAD`. - **Read-only replicas / maintenance mode**: some teams flip write endpoints to 405, though 503 with `Retry-After` is a better fit for a *temporary* condition — 405 implies a property of the resource, not an outage. ## Caching note RFC 9111 lists 405 among the statuses that are heuristically cacheable. If your `Allow` set changes per deployment or per feature flag, a cached 405 can outlive the truth; sending `Cache-Control: no-store` on such responses avoids a confusing stale-405 class of bug. ## Body content 405 may carry a body, and a helpful one repeats the allowed methods in your standard error shape, e.g. `{"code":"METHOD_NOT_ALLOWED","allowed":["GET","HEAD"]}`. The body is a convenience; the `Allow` header is the contract.
- A client sends POST to a path that only accepts PUT and your router returns 404. What is wrong with that, and how do you fix it?It conflates two different failures: 404 says the target does not exist, so the developer hunts a routing or deployment problem instead of a wrong verb. The fix is to match the path first and, on a method mismatch, return 405 with an `Allow` header listing the route's real methods. Most frameworks support this once path and method matching are separated.
- Why can a missing OPTIONS handler surface as a CORS failure in the browser?For non-simple cross-origin requests the browser first sends an OPTIONS preflight. If no OPTIONS handler exists, the server answers 405 (or 404) with no CORS headers, so the browser blocks the real request and reports a CORS error. The underlying bug is method handling, which is why every route should answer OPTIONS with `Allow` plus the CORS headers.
saying these in an interview costs you the question
- Returning 405 without the mandatory Allow header
- Using 501 for "this endpoint doesn't support DELETE" — that is 405, and 501 is a 5xx
- Returning 404 for a wrong method on an existing path
- Answering 405 to HEAD on a resource that supports GET
- Assuming Allow is a request header or that it describes the whole server