{"record":{"id":"7f65140fe4551d38","repo":"rwf2/Rocket","slug":"unexpectedeof-7f6514","errorCode":"UnexpectedEof","errorMessage":"data limit exceeded","messagePattern":"data limit exceeded","errorType":"http","errorClass":"rocket::serde::json::Error","httpStatus":413,"severity":"error","filePath":"core/lib/src/serde/json.rs","lineNumber":187,"sourceCode":"    /// ```\n    #[inline(always)]\n    pub fn into_inner(self) -> T {\n        self.0\n    }\n}\n\nimpl<'r, T: Deserialize<'r>> Json<T> {\n    fn from_str(s: &'r str) -> Result<Self, Error<'r>> {\n        serde_json::from_str(s).map(Json).map_err(|e| Error::Parse(s, e))\n    }\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Result<Self, Error<'r>> {\n        let limit = req.limits().get(\"json\").unwrap_or(Limits::JSON);\n        let string = match data.open(limit).into_string().await {\n            Ok(s) if s.is_complete() => s.into_inner(),\n            Ok(_) => {\n                let eof = io::ErrorKind::UnexpectedEof;\n                return Err(Error::Io(io::Error::new(eof, \"data limit exceeded\")));\n            },\n            Err(e) => return Err(Error::Io(e)),\n        };\n\n        Self::from_str(local_cache!(req, string))\n    }\n}\n\n#[crate::async_trait]\nimpl<'r, T: Deserialize<'r>> FromData<'r> for Json<T> {\n    type Error = Error<'r>;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {\n        match Self::from_data(req, data).await {\n            Ok(value) => Outcome::Success(value),\n            Err(Error::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {\n                Outcome::Error((Status::PayloadTooLarge, Error::Io(e)))\n            },","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/rwf2/Rocket/blob/3a54d079aef060a8f732bd04ea54b0581a604087/core/lib/src/serde/json.rs#L169-L205","documentation":"Runtime error from the Json<T> FromData guard (core/lib/src/serde/json.rs): the request body is opened with the 'json' limit (Limits::JSON, default 1 MiB); if the stream is truncated at the limit (into_string returns an incomplete Capped), Rocket returns io::ErrorKind::UnexpectedEof 'data limit exceeded', and the FromData impl maps it to 413 PayloadTooLarge. This is Rocket's guard against unbounded JSON bodies, not a client parsing error.","triggerScenarios":"POST/PUT with Content-Type: application/json and a body larger than limits.json (default 1 MiB) to a route guarded by Json<T>. The guard fails before serde deserialization ever runs, yielding 413.","commonSituations":"APIs accepting base64-encoded images or large arrays in JSON; batch endpoints; front-ends that grew payloads over time and only now crossed 1 MiB; proxies that don't enforce their own body limit so Rocket's fires first.","solutions":["Raise the limit in Rocket.toml: [default.limits] json = \"5 MiB\"","Redesign the API to stream large payloads (multipart with TempFile, or chunked upload endpoints) instead of huge JSON","Handle the 413 in a catcher or client-side by splitting the request","Confirm with curl --data-binary @big.json -H 'Content-Type: application/json' which side truncates"],"exampleFix":"# before\n# Rocket.toml (json defaults to 1 MiB)\n#[post(\"/report\", data = \"<r>\")]\nfn report(r: Json<Report>) { }\n\n# after\n# Rocket.toml\n[default.limits]\njson = \"8 MiB\"\n\n#[post(\"/report\", data = \"<r>\")]\nfn report(r: Json<Report>) { }","handlingStrategy":"try-catch","validationCode":"// route around the guard for oversized payloads: check Content-Length first\n#[post(\"/report\", data = \"<data>\")]\nfn report(req: &Request<'_>, data: Data<'_>) -> Status {\n    let limit: usize = 5 * 1024 * 1024;\n    if let Some(len) = req.headers().get_one(\"Content-Length\").and_then(|v| v.parse().ok()) {\n        if len > limit { return Status::PayloadTooLarge; }\n    }\n    // small enough: continue (guard would also work here)\n    Status::Ok\n}","typeGuard":null,"tryCatchPattern":"// client side: handle 413 by splitting or compressing the payload\nmatch client.post(\"/report\").json(&body).send().await {\n    resp if resp.status() == StatusCode::PAYLOAD_TOO_LARGE => { /* split/retry smaller */ }\n    resp => { /* normal path */ }\n}","preventionTips":["Declare limits.json explicitly in Rocket.toml for every profile — never assume the 1 MiB default","Keep JSON payloads small by design; move binaries to multipart/TempFile endpoints","Add tests with oversized fixtures so limit regressions fail in CI"],"tags":["rust","rocket","json","limits","runtime","request-body"],"backgroundTag":"request-body-too-large","analyzedSha":"3a54d079aef060a8f732bd04ea54b0581a604087","analyzedAt":"2026-08-16T22:01:48.395Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}