quickwit-oss/quickwit · error · UnsupportedMediaType
UnsupportedMediaType
Error message
UnsupportedMediaType
What it means
`UnsupportedMediaType` is a warp custom rejection raised in `extract_config_format` (quickwit/quickwit-serve/src/format.rs:105) when a REST handler that accepts an index/source/index-template config receives a `Content-Type` header whose MIME subtype is not `json`, `toml`, or `yaml`. Quickwit only knows how to deserialize the posted configuration body in those three formats, so any other content type is rejected with an HTTP 415 Unsupported Media Type response.
Solutions
- Set the request `Content-Type` header to `application/json` (or `application/toml` / `application/yaml` to match the body encoding).
- Ensure the body actually matches the declared Content-Type (JSON body with JSON header, TOML body with TOML header).
- Avoid vendor MIME suffixes; use plain `application/json` rather than `application/vnd.api+json`, since only the bare subtype is matched.
- If using a generated HTTP client, override the default content type for these config endpoints.
Example fix
// before curl -X POST http://localhost:7280/indexes -H 'Content-Type: text/plain' --data-binary @index-config.yaml // after curl -X POST http://localhost:7280/indexes -H 'Content-Type: application/yaml' --data-binary @index-config.yaml
Defensive patterns
Strategy: validation
Validate before calling
// Client-side check before sending
const ALLOWED = new Set(['application/json', 'application/toml', 'application/yaml']);
if (!ALLOWED.has(contentType)) {
throw new Error(`Content-Type must be one of ${[...ALLOWED]}, got: ${contentType}`);
} Type guard
fn is_supported_config_content_type(content_type: &str) -> bool {
matches!(
content_type,
"application/json" | "application/toml" | "application/yaml"
| "text/yaml" | "text/x-yaml"
)
} Try / catch
// Client side: catch the 415 rejection and report the offending header
try {
const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body });
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
} catch (e) {
if (String(e).includes('415') || String(e).includes('UnsupportedMediaType')) {
console.error('Set Content-Type to application/json, application/toml, or application/yaml');
}
throw e;
} Prevention
- Always set Content-Type explicitly when posting index/source/template configs; never rely on HTTP client defaults.
- Match the header to the actual body encoding (JSON body -> application/json, TOML body -> application/toml).
- Avoid vendor or suffixed MIME types (application/vnd.*+json); Quickwit matches only the plain subtype.
- Add a preflight validation in CI scripts or SDK wrappers that whitelists content types for Quickwit config endpoints.
- When a 415 comes back, immediately inspect the Content-Type header before debugging the body.
When it happens
Trigger: Sending POST/PUT to /indexes, /indexes/{index}/sources, or index-template endpoints with a `Content-Type` such as `application/xml`, `text/plain`, `application/x-www-form-urlencoded`, or a vendor type whose subtype Quickwit does not map (e.g. `application/hal+json` resolves to subtype `hal+json`, not `json`).
Common situations: curl or HTTP client defaulting to no/incorrect Content-Type; REST client tools posting form data; SDK-generated clients sending vendor MIME types like `application/vnd.api+json`; copy-pasted requests where the body is JSON but the header says `text/plain`.
Related errors
- Encountered unknown command: code
- Failed to fetch splits.
- `index_id` in config file does not match index_id from…
- path based file sources are limited to a local usage…
- `source_id` in config file does not match source_id from…
AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08).
Data as JSON: /api/errors/b93c70e4040a8a80.
Report an issue: GitHub.
Appendix: source
Thrown at quickwit/quickwit-serve/src/format.rs:105
#[error(
"request's content-type is not supported: supported media types are `application/json`, \
`application/toml`, and `application/yaml`"
)]
pub(crate) struct UnsupportedMediaType;
impl warp::reject::Reject for UnsupportedMediaType {}
pub(crate) fn extract_config_format()
-> impl Filter<Extract = (ConfigFormat,), Error = Rejection> + Copy {
warp::filters::header::optional::<mime_guess::Mime>(CONTENT_TYPE.as_str()).and_then(
|mime_opt: Option<mime_guess::Mime>| {
if let Some(mime) = mime_opt {
let config_format = match mime.subtype().as_str() {
"json" => ConfigFormat::Json,
"toml" => ConfigFormat::Toml,
"yaml" => ConfigFormat::Yaml,
_ => {
return futures::future::err(warp::reject::custom(UnsupportedMediaType));
}
};
return futures::future::ok(config_format);
}
futures::future::ok(ConfigFormat::Json)
},
)
}
View on GitHub (pinned to a39730c5cd)