{"record":{"id":"8d7a49f9961d41a8","repo":"zed-industries/zed","slug":"missing-content-type-header","errorCode":null,"errorMessage":"missing Content-Type header","messagePattern":"missing Content-Type header","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/agent/src/tools/fetch_tool.rs","lineNumber":119,"sourceCode":"                \"refusing to follow redirect to non-HTTP(S) URL {target}\"\n            );\n            return Ok(FetchStep::Redirect(target.to_string()));\n        }\n\n        let mut body = Vec::new();\n        response\n            .body_mut()\n            .read_to_end(&mut body)\n            .await\n            .context(\"error reading response body\")?;\n\n        if status.is_client_error() {\n            let text = String::from_utf8_lossy(body.as_slice());\n            bail!(\"status error {}, response: {text:?}\", status.as_u16());\n        }\n\n        let Some(content_type) = response.headers().get(\"content-type\") else {\n            bail!(\"missing Content-Type header\");\n        };\n        let content_type = content_type\n            .to_str()\n            .context(\"invalid Content-Type header\")?;\n\n        let content_type = if content_type.starts_with(\"text/plain\") {\n            ContentType::Plaintext\n        } else if content_type.starts_with(\"application/json\") {\n            ContentType::Json\n        } else {\n            ContentType::Html\n        };\n\n        let text = match content_type {\n            ContentType::Html => {\n                let mut handlers: Vec<TagHandler> = vec![\n                    Rc::new(RefCell::new(markdown::WebpageChromeRemover)),\n                    Rc::new(RefCell::new(markdown::ParagraphHandler)),","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/agent/src/tools/fetch_tool.rs#L101-L137","documentation":"After handling redirects and 4xx statuses, the fetch tool needs the Content-Type header to pick a parser: text/plain maps to plaintext, application/json to json, anything else to html (crates/agent/src/tools/fetch_tool.rs:119-130). A response with no Content-Type at all fails with 'missing Content-Type'. Note only client errors are checked earlier, so a 5xx or an empty 204 without the header also lands here.","triggerScenarios":"A server responds without a Content-Type header: bare or minimal HTTP servers, some redirects to endpoints that omit it, 204/no-content responses, misconfigured proxies stripping headers.","commonSituations":"Fetching from hand-rolled dev servers or internal endpoints that skip headers; empty-body responses; corporate proxies or gateways that drop headers.","solutions":["Inspect the raw response with curl -I <url> to confirm the header is absent.","If you control the server, set Content-Type on every response (application/json, text/html, text/plain).","If not, download the resource yourself (curl -o file) and point the agent at the local file.","Prefer endpoints that return proper headers (official docs and APIs) over hand-rolled ones."],"exampleFix":"# before: endpoint sends no Content-Type\ncurl -I http://localhost:8000/data   # no content-type in response\n\n# after: set it in the handler\nResponse::builder()\n    .header(\"content-type\", \"application/json\")\n    .body(body)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"let result = tool.run(input, cx).await;\nmatch result {\n    Ok(output) => { /* use content */ }\n    Err(err) if err.to_string().contains(\"missing Content-Type\") => {\n        // fetch the resource out-of-band and reference a local copy\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["curl -I the URL to confirm the server omits Content-Type before debugging further.","If you own the server, set Content-Type on every response including errors and 204s.","Point the agent at official endpoints that return proper headers."],"tags":["http","fetch","missing-header","agent-tool","zed"],"backgroundTag":"missing-response-header","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}