HTTP 405 Method Not Allowed — Wrong Verb
Fix 405 Method Not Allowed by matching the HTTP verb to the route, checking the server Allow header, and correcting client or proxy method handling.
Symptoms
- The API returns 405 with "Method Not Allowed" for a route that exists
- GET works but POST returns 405
- A proxy or preflight changes the method the server sees
Possible causes
- The route is registered for different verbs than the client uses
- The client sends a verb the handler does not implement (undefined POST on a GET route)
- A trailing slash or proxy rewrite maps the request to a different route
Diagnosis steps
Read the Allow header
curl -i -X POST https://api.example.com/itemsInterpretation
The Allow header lists the methods the route actually supports, revealing the correct verb.
Compare route registration with the request
grep -rn "app.get\|app.post\|router.put" src/routesInterpretation
Confirming the registered verbs against the client call finds the mismatch.
Root cause
The server found a route matching the path but not the HTTP method, so it responds 405 and advertises the allowed methods in the Allow header. The path exists; the verb is wrong.
Fix
Use the verb the route declares, register the needed method if the operation is legitimate, and ensure proxies and clients preserve the intended method (PATCH versus PUT, POST versus GET).
Risk note
Changing a GET route to accept POST to silence the error can break caching and idempotency semantics.
Verify the fix
Send the request with the correct verb and confirm 2xx; verify a wrong verb still returns 405 with an accurate Allow header.
Symptoms
This debugging guide addresses “HTTP 405 Method Not Allowed — Wrong Verb”. Start from the symptoms, follow the ordered diagnostics, and confirm each hypothesis before moving on; the fix and verification steps then close the loop.
Observed symptoms include:
- The API returns 405 with “Method Not Allowed” for a route that exists
- GET works but POST returns 405
- A proxy or preflight changes the method the server sees
Reproduce and Diagnose
Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.
Step 1: Read the Allow header
curl -i -X POST https://api.example.com/items
The Allow header lists the methods the route actually supports, revealing the correct verb.
Step 2: Compare route registration with the request
grep -rn "app.get\|app.post\|router.put" src/routes
Confirming the registered verbs against the client call finds the mismatch.
Likely contributors, in order of frequency:
- The route is registered for different verbs than the client uses
- The client sends a verb the handler does not implement (undefined POST on a GET route)
- A trailing slash or proxy rewrite maps the request to a different route
Root Cause
The server found a route matching the path but not the HTTP method, so it responds 405 and advertises the allowed methods in the Allow header. The path exists; the verb is wrong.
The Fix
Use the verb the route declares, register the needed method if the operation is legitimate, and ensure proxies and clients preserve the intended method (PATCH versus PUT, POST versus GET).
Watch out: Changing a GET route to accept POST to silence the error can break caching and idempotency semantics.
// Express: register the needed verb explicitly
router.get('/items', listItems);
router.post('/items', createItem);
// client: use the verb the route declares
await fetch('/items', { method: 'POST', body: JSON.stringify(payload) });
# inspect allowed methods
curl -i -X OPTIONS https://api.example.com/items
Verify and Prevent
Send the request with the correct verb and confirm 2xx; verify a wrong verb still returns 405 with an accurate Allow header.
Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.
This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.