calcom/cal.diy · warning · HttpError
Unsupported Content-Type. Expected ${contentType}
Error message
Unsupported Content-Type. Expected ${contentType} What it means
Thrown by parseRequestData (HttpError, HTTP 415 Unsupported Media Type) when the request Content-Type is neither application/json, application/x-www-form-urlencoded, nor multipart/form-data. The message echoes the unsupported content-type so the caller knows what was received vs expected.
Source
Thrown at apps/web/app/api/parseRequestData.ts:50
if (contentType.includes("application/json")) {
try {
return await req.json();
} catch (e) {
log.error(`Invalid JSON: ${e} from path ${req.nextUrl}`);
throw new HttpError({ statusCode: 400, message: "Bad Request (Invalid JSON)" });
}
}
if (contentType.includes("application/x-www-form-urlencoded")) {
return await parseUrlFormData(req);
}
if (contentType.includes("multipart/form-data")) {
return await parseMultiFormData(req);
}
log.error(`Unsupported content type: ${contentType} from path ${req.nextUrl}`);
throw new HttpError({ statusCode: 415, message: `Unsupported Content-Type. Expected ${contentType}` });
}
View on GitHub (pinned to 176037d0af)
Solutions
- Set Content-Type to one of: application/json, application/x-www-form-urlencoded, or multipart/form-data on the request.
- Default the client to application/json for structured payloads.
- If you genuinely need a new content-type, extend parseRequestData to handle it rather than relying on the fallback.
Example fix
// before
await fetch('/api/x', { method: 'POST', body: 'hello' }); // Content-Type defaults to text/plain
// after
await fetch('/api/x', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ msg: 'hello' }),
}); Defensive patterns
Strategy: validation
Validate before calling
// Send a supported Content-Type
const SUPPORTED = ['application/json', 'application/x-www-form-urlencoded', 'multipart/form-data'];
if (!SUPPORTED.some(t => contentType.startsWith(t))) {
throw new Error(`Unsupported Content-Type: ${contentType}`);
}
await fetch('/api/x', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body }); Type guard
function isSupportedContentType(ct: string): boolean {
return ['application/json', 'application/x-www-form-urlencoded', 'multipart/form-data']
.some(t => ct.includes(t));
} Try / catch
try {
await parseRequestData(req);
} catch (e) {
if (e instanceof HttpError && e.statusCode === 415) {
return Response.json({ error: e.message }, { status: 415 });
}
throw e;
} Prevention
- Default clients to application/json for structured data.
- Explicitly set Content-Type on every request rather than relying on defaults.
- Extend parseRequestData if a new content-type must be supported.
When it happens
Trigger: POST/PUT with a Content-Type the dispatcher does not handle, e.g. text/plain, application/xml, an empty type, or a multipart type with an unexpected parameter.
Common situations: Client forgot to set Content-Type (defaults to text/plain in some fetch setups), sending XML/text to a JSON-only endpoint, custom content-type not yet supported, charset-only variations.
Related errors
- Bad Request (Invalid JSON)
- Bad Request (Invalid Url Form Data)
- Bad Request (Invalid Multi Form Data)
- ApiKeysService -Cannot set both apiKeyDaysValid and apiKeyNe
- teamId is required for team events, please provide a valid t
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/ea417a2f926d1d81.
Report an issue: GitHub.