vllm-project/vllm · error · Error

messagepack decode failed for {target_type}: {message}

Error message

messagepack decode failed for {target_type}: {message}

What it means

A MessagePack deserialization failure. Every frame received from the engine is decoded via rmp_serde::from_slice (rust/src/engine-core-client/src/protocol/mod.rs:66), and unknown EngineCoreOutput shapes map to Error::Decode in protocol/output.rs:299. target_type tells you which struct failed to materialize; message carries the underlying rmp_serde error.

Source

Thrown at rust/src/engine-core-client/src/error.rs:22

use std::sync::Arc;
use std::time::Duration;

use thiserror::Error;
use thiserror_ext::Macro;

use crate::protocol::utility::UtilityCallId;

pub type Result<T> = std::result::Result<T, Error>;

/// Public error type for the Rust engine-core client.
#[derive(Debug, Error, Macro)]
pub enum Error {
    #[error("messagepack encode failed for {target_type}: {message}")]
    Encode {
        target_type: &'static str,
        message: String,
    },
    #[error("messagepack decode failed for {target_type}: {message}")]
    Decode {
        target_type: &'static str,
        message: String,
    },
    #[error("messagepack value decode failed")]
    ValueDecode(#[from] rmpv::decode::Error),
    #[error("messagepack ext value decode failed: {message}")]
    ExtValueDecode { message: String },
    #[error("invalid structured outputs params: {message}")]
    InvalidStructuredOutputsParams { message: String },
    #[error("io error")]
    Io(#[from] std::io::Error),
    #[error("transport error")]
    Transport(#[from] zeromq::ZmqError),
    #[error("ZMQ runtime task failed")]
    ZmqRuntimeTask(#[from] tokio::task::JoinError),
    #[error("engine core reported fatal failure")]
    EngineCoreDead,

View on GitHub (pinned to c794754062)

Solutions

  1. Pin the vLLM/Python engine version to one the Rust crate was built against
  2. Inspect message and target_type: an 'unknown variant' points to a new message kind; 'invalid type' points to a changed field
  3. Extend the corresponding Rust struct/enum (usually with #[serde(default)] or a new variant) and add a decoding test with the raw frame
  4. Capture the raw frame with tracing (RUST_LOG=engine_core_client=trace) to feed a reproduction
Defensive patterns

Strategy: try-catch

Type guard

fn is_decode_error(e: &engine_core_client::Error) -> bool {
    matches!(e, engine_core_client::Error::Decode { .. })
}

Try / catch

match result {
    Err(engine_core_client::Error::Decode { target_type, message }) => {
        tracing::error!(target_type, message, "wire format mismatch; check engine version");
        return; // do not retry: deterministic schema mismatch
    }
    other => other?,
}

Prevention

When it happens

Trigger: The engine sends bytes that do not deserialize into the expected type: decoding a ReadyMessage/EngineCoreReadyResponse handshake payload, an EngineCoreOutputs frame with an unrecognized message union tag (output.rs:299 catch-all), or any response whose field types differ from the Rust struct.

Common situations: Version skew: Python vLLM added/renamed a wire field and the Rust crate has not caught up (see the comment at transport.rs:464 referencing vLLM commit c8d98f81 changing the handshake payload). A mismatched vLLM image vs crate version. Unexpected error payloads (e.g. tracebacks) arriving on the output socket.

Related errors


AI-assisted analysis of vllm-project/vllm@c794754062 (2026-08-14). Data as JSON: /api/errors/01c7ca0c93863a00. Report an issue: GitHub.