rwf2/Rocket · error · rocket::serde::msgpack::Error
UnexpectedEof
UnexpectedEof
Error message
data limit exceeded
What it means
Runtime error from the MsgPack<T> FromData guard (core/lib/src/serde/msgpack.rs): the body is opened with the 'msgpack' limit (Limits::MESSAGE_PACK, default 1 MiB); if reading stops at that limit with more data remaining (into_bytes returns an incomplete Capped), the guard errors with io::ErrorKind::UnexpectedEof 'data limit exceeded' wrapped in Error::InvalidDataRead, failing the MsgPack guard (typically 413/400 depending on catcher). Same policy as the JSON guard, applied to application/msgpack bodies.
Source
Thrown at core/lib/src/serde/msgpack.rs:185
/// ```
#[inline(always)]
pub fn into_inner(self) -> T {
self.0
}
}
impl<'r, T: Deserialize<'r>> MsgPack<T> {
fn from_bytes(buf: &'r [u8]) -> Result<Self, Error> {
rmp_serde::from_slice(buf).map(MsgPack)
}
async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Result<Self, Error> {
let limit = req.limits().get("msgpack").unwrap_or(Limits::MESSAGE_PACK);
let bytes = match data.open(limit).into_bytes().await {
Ok(buf) if buf.is_complete() => buf.into_inner(),
Ok(_) => {
let eof = io::ErrorKind::UnexpectedEof;
return Err(Error::InvalidDataRead(io::Error::new(eof, "data limit exceeded")));
},
Err(e) => return Err(Error::InvalidDataRead(e)),
};
Self::from_bytes(local_cache!(req, bytes))
}
}
#[crate::async_trait]
impl<'r, T: Deserialize<'r>> FromData<'r> for MsgPack<T> {
type Error = Error;
async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {
match Self::from_data(req, data).await {
Ok(value) => Outcome::Success(value),
Err(Error::InvalidDataRead(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
Outcome::Error((Status::PayloadTooLarge, Error::InvalidDataRead(e)))
},View on GitHub (pinned to 3a54d079ae)
Solutions
- Raise the limit: Rocket.toml [default.limits] msgpack = "10 MiB"
- Split large binary payloads into multiple requests or use Data<'_>/TempFile streaming instead of MsgPack<T>
- Add a catcher for the resulting status so clients get a clear 'payload too large' message
- Verify with a sized test payload (head -c 2M /dev/urandom as msgpack body)
Example fix
# before
# Rocket.toml (msgpack defaults to 1 MiB)
#[post("/ingest", data = "<batch>")]
fn ingest(batch: MsgPack<Batch>) { }
# after
# Rocket.toml
[default.limits]
msgpack = "10 MiB"
#[post("/ingest", data = "<batch>")]
fn ingest(batch: MsgPack<Batch>) { } Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check size for msgpack uploads
#[post("/ingest", data = "<data>")]
fn ingest(req: &Request<'_>, data: Data<'_>) -> Status {
let limit: usize = 10 * 1024 * 1024;
if let Some(len) = req.headers().get_one("Content-Length").and_then(|v| v.parse::<usize>().ok()) {
if len > limit { return Status::PayloadTooLarge; }
}
Status::Ok
} Try / catch
// server: catcher translating guard failure for msgpack clients
#[catch(413)]
fn too_large(_: &Request) -> (Status, &('static str)) {
(Status::PayloadTooLarge, "msgpack body exceeds configured limit")
} Prevention
- Set limits.msgpack deliberately when accepting packed binary batches
- Chunk large binary streams instead of one giant msgpack document
- Monitor 413 rates to catch payload growth before clients do
When it happens
Trigger: POSTing an application/msgpack (or msgpack content-type) body larger than limits.msgpack (default 1 MiB) to a route with a MsgPack<T> guard.
Common situations: Binary-heavy APIs (embedded telemetry, sensor batches, serialized ML features) packing large blobs into one msgpack document; payload growth after launch; msgpack chosen specifically for large binary data without raising the limit.
Related errors
AI-assisted analysis of rwf2/Rocket@3a54d079ae (2026-08-16).
Data as JSON: /api/errors/c2461dc2a55b2f8a.
Report an issue: GitHub.