{"record":{"id":"b93c70e4040a8a80","repo":"quickwit-oss/quickwit","slug":"unsupportedmediatype","errorCode":null,"errorMessage":"UnsupportedMediaType","messagePattern":"UnsupportedMediaType","errorType":"http","errorClass":"UnsupportedMediaType","httpStatus":415,"severity":"error","filePath":"quickwit/quickwit-serve/src/format.rs","lineNumber":105,"sourceCode":"#[error(\n    \"request's content-type is not supported: supported media types are `application/json`, \\\n     `application/toml`, and `application/yaml`\"\n)]\npub(crate) struct UnsupportedMediaType;\n\nimpl warp::reject::Reject for UnsupportedMediaType {}\n\npub(crate) fn extract_config_format()\n-> impl Filter<Extract = (ConfigFormat,), Error = Rejection> + Copy {\n    warp::filters::header::optional::<mime_guess::Mime>(CONTENT_TYPE.as_str()).and_then(\n        |mime_opt: Option<mime_guess::Mime>| {\n            if let Some(mime) = mime_opt {\n                let config_format = match mime.subtype().as_str() {\n                    \"json\" => ConfigFormat::Json,\n                    \"toml\" => ConfigFormat::Toml,\n                    \"yaml\" => ConfigFormat::Yaml,\n                    _ => {\n                        return futures::future::err(warp::reject::custom(UnsupportedMediaType));\n                    }\n                };\n                return futures::future::ok(config_format);\n            }\n            futures::future::ok(ConfigFormat::Json)\n        },\n    )\n}\n","sourceCodeStart":87,"sourceCodeEnd":114,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-serve/src/format.rs#L87-L114","documentation":"`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.","triggerScenarios":"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`).","commonSituations":"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`.","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."],"exampleFix":"// before\ncurl -X POST http://localhost:7280/indexes -H 'Content-Type: text/plain' --data-binary @index-config.yaml\n// after\ncurl -X POST http://localhost:7280/indexes -H 'Content-Type: application/yaml' --data-binary @index-config.yaml","handlingStrategy":"validation","validationCode":"// Client-side check before sending\nconst ALLOWED = new Set(['application/json', 'application/toml', 'application/yaml']);\nif (!ALLOWED.has(contentType)) {\n  throw new Error(`Content-Type must be one of ${[...ALLOWED]}, got: ${contentType}`);\n}","typeGuard":"fn is_supported_config_content_type(content_type: &str) -> bool {\n  matches!(\n    content_type,\n    \"application/json\" | \"application/toml\" | \"application/yaml\"\n      | \"text/yaml\" | \"text/x-yaml\"\n  )\n}","tryCatchPattern":"// Client side: catch the 415 rejection and report the offending header\ntry {\n  const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body });\n  if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);\n} catch (e) {\n  if (String(e).includes('415') || String(e).includes('UnsupportedMediaType')) {\n    console.error('Set Content-Type to application/json, application/toml, or application/yaml');\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["http","rest-api","content-type","warp"],"backgroundTag":"unsupported-media-type","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}