{"record":{"id":"e7ee13d12870cd3e","repo":"leptos-rs/leptos","slug":"couldn-t-parse-boundary","errorCode":null,"errorMessage":"couldn't parse boundary","messagePattern":"couldn't parse boundary","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server_fn/src/codec/multipart.rs","lineNumber":88,"sourceCode":"        Request::try_new_post_multipart(\n            path,\n            accepts,\n            multi.into_client_data().unwrap(),\n        )\n    }\n}\n\nimpl<E, T, Request> FromReq<MultipartFormData, Request, E> for T\nwhere\n    Request: Req<E> + Send + 'static,\n    T: From<MultipartData>,\n    E: FromServerFnError + Send + Sync,\n{\n    async fn from_req(req: Request) -> Result<Self, E> {\n        let boundary = req\n            .to_content_type()\n            .and_then(|ct| multer::parse_boundary(ct).ok())\n            .expect(\"couldn't parse boundary\");\n        let stream = req.try_into_stream()?;\n        let data = multer::Multipart::new(\n            stream.map(|data| data.map_err(|e| ServerFnErrorWrapper(E::de(e)))),\n            boundary,\n        );\n        Ok(MultipartData::Server(data).into())\n    }\n}\n","sourceCodeStart":70,"sourceCodeEnd":97,"githubUrl":"https://github.com/leptos-rs/leptos/blob/32d20f6c9d517451d77beb68d88c7716823dac41/server_fn/src/codec/multipart.rs#L70-L97","documentation":"MultipartData::from_req extracts the boundary from the request's Content-Type header via multer::parse_boundary. If the header is missing, malformed, or lacks a valid boundary parameter, the .ok() yields None and .expect panics with 'couldn't parse boundary'. The library throws it because a multipart stream cannot be demarcated without a boundary.","triggerScenarios":"Calling a multipart server function (server_fn multipart codec) from a client that sends Content-Type: multipart/form-data without a boundary parameter, omits the Content-Type header entirely, or sends a different content type (e.g. application/json) to a multipart-encoding endpoint.","commonSituations":"Hand-rolled fetch/reqwest calls to a server fn that forgot to set multipart headers; proxies or CDNs stripping/rewriting the Content-Type header; client SDK built with a different codec than the server fn declares; tests posting raw bodies without a generated boundary.","solutions":["Use the generated client (server_fn client) instead of a hand-rolled request so the boundary is generated automatically","Ensure the request's Content-Type is multipart/form-data with a boundary parameter, e.g. multipart/form-data; boundary=xyz","If calling manually with multer on the client side, pass the same boundary string used to build the body","Inspect intermediate proxies/gateways for Content-Type header mutation"],"exampleFix":"// before\nfetch(\"/api/upload\", { method: \"POST\", body: formData }); // header may be dropped/mangled\n// after\nfetch(\"/api/upload\", { method: \"POST\", body: formData }); // let browser set multipart/form-data; boundary=... (do NOT set Content-Type manually)\n","handlingStrategy":"validation","validationCode":"fn has_valid_boundary(headers: &http::HeaderMap) -> bool {\n    headers.get(http::header::CONTENT_TYPE)\n        .and_then(|v| v.to_str().ok())\n        .map(|ct| ct.starts_with(\"multipart/\") && ct.contains(\"boundary=\"))\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"// panic, not Result: pre-validate Content-Type; if calling from wasm, wrap the whole\n// request in catch_unwind is impractical — validate before send instead.\nif !has_valid_boundary(&req.headers()) { return Err(ServerFnError::Request(\"missing multipart boundary\".into())); }","preventionTips":["Never set Content-Type manually for FormData — let the HTTP client generate boundary","Use the generated server-fn client rather than hand-built requests","Check that proxies/CDNs don't rewrite Content-Type","Add an integration test posting real multipart bodies"],"tags":["http","multipart","panic"],"backgroundTag":"multipart-boundary-parse","analyzedSha":"32d20f6c9d517451d77beb68d88c7716823dac41","analyzedAt":"2026-09-01T18:55:42.580Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}