HTTP 415 Unsupported Media Type — Content-Type Mismatch
Fix 415 Unsupported Media Type by sending the Content-Type the server expects and configuring the parser or framework to accept it.
Symptoms
- The API returns 415 Unsupported Media Type for a POST
- curl works when you add a header the client omits
- A framework rejects text/plain or a missing Content-Type
Possible causes
- The request omits Content-Type or sends one the parser does not accept
- The body is JSON but is sent as text/plain
- A multipart or vendor media type is not configured on the route
Diagnosis steps
Reproduce with an explicit Content-Type
curl -i -X POST https://api.example.com/items -d '{"a":1}'Interpretation
Omitting the header usually yields 415; adding -H "Content-Type: application/json" should fix it.
Confirm the accepted types
curl -i -X OPTIONS https://api.example.com/items -H 'Access-Control-Request-Headers: content-type'Interpretation
The preflight and server config reveal which media types the endpoint accepts.
Root cause
The server could not parse the request because its Content-Type was missing or not among the media types the endpoint accepts, so it responds 415 without attempting to read the body.
Fix
Send the correct Content-Type (application/json for JSON), ensure the client library sets it, and configure the framework route to accept the intended media types.
Risk note
Sending Content-Type: application/json with a non-JSON body yields a different parse error; keep header and body consistent.
Verify the fix
Retry with the correct Content-Type and confirm 2xx; verify the wrong type still returns 415.
Symptoms
The error “HTTP 415 Unsupported Media Type — Content-Type Mismatch” points at a specific failure mode. This guide documents the symptoms you can observe, the commands that isolate the cause, the root cause, the fix, and the checks that prove the fix works.
Observed symptoms include:
- The API returns 415 Unsupported Media Type for a POST
- curl works when you add a header the client omits
- A framework rejects text/plain or a missing Content-Type
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: Reproduce with an explicit Content-Type
curl -i -X POST https://api.example.com/items -d '{"a":1}'
Omitting the header usually yields 415; adding -H “Content-Type: application/json” should fix it.
Step 2: Confirm the accepted types
curl -i -X OPTIONS https://api.example.com/items -H 'Access-Control-Request-Headers: content-type'
The preflight and server config reveal which media types the endpoint accepts.
Likely contributors, in order of frequency:
- The request omits Content-Type or sends one the parser does not accept
- The body is JSON but is sent as text/plain
- A multipart or vendor media type is not configured on the route
Root Cause
The server could not parse the request because its Content-Type was missing or not among the media types the endpoint accepts, so it responds 415 without attempting to read the body.
The Fix
Send the correct Content-Type (application/json for JSON), ensure the client library sets it, and configure the framework route to accept the intended media types.
Watch out: Sending Content-Type: application/json with a non-JSON body yields a different parse error; keep header and body consistent.
// fetch: set the header and body together
await fetch('/items', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ a: 1 }),
});
# multipart uploads must not hand-set Content-Type (the boundary is automatic)
curl -X POST https://api.example.com/upload -F '[email protected]'
Verify and Prevent
Retry with the correct Content-Type and confirm 2xx; verify the wrong type still returns 415.
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.