vllm-project/vllm · error · Error
unsupported auxiliary frame(s): expected 1 frame, got {frame
Error message
unsupported auxiliary frame(s): expected 1 frame, got {frame_count} What it means
Error::UnsupportedAuxFrames { frame_count } reports that a request or message carried an auxiliary-frame count other than the single frame the current protocol supports: 'expected 1 frame, got {frame_count}'. Aux frames are the zero-copy mechanism that moves large tensors (multimodal embeddings, request tensors exceeding msgpack_zero_copy_threshold) out of the msgpack body into trailing ZMQ frames (protocol/request.rs extract_aux_frames, transport.rs:534-538 assembles 3 + aux frames).
Source
Thrown at rust/src/engine-core-client/src/error.rs:58
EngineCoreDead,
#[error("startup handshake timed out while waiting for {stage} after {timeout:?}")]
HandshakeTimeout {
stage: &'static str,
timeout: Duration,
},
#[error("engine input registration timed out after {timeout:?}")]
InputRegistrationTimeout { timeout: Duration },
#[error("unexpected engine id in startup handshake: expected {expected:?}, got {actual:?}")]
UnexpectedHandshakeIdentity { expected: Vec<u8>, actual: Vec<u8> },
#[error("unexpected startup handshake message: {message}")]
UnexpectedHandshakeMessage { message: String },
#[error("unexpected non-control output on coordinator path: {message}")]
UnexpectedCoordinatorOutput { message: String },
#[error("unexpected output on main dispatcher path: {message}")]
UnexpectedDispatcherOutput { message: String },
#[error("coordinator requires a Python-compatible two-byte engine id, got {engine_id:?}")]
UnsupportedCoordinatorEngineId { engine_id: Vec<u8> },
#[error("unsupported auxiliary frame(s): expected 1 frame, got {frame_count}")]
UnsupportedAuxFrames { frame_count: usize },
#[error("external coordinator mode is not implemented yet")]
UnsupportedExternalCoordinator,
#[error("unsupported field `{field}` in {context}")]
UnsupportedField {
context: &'static str,
field: &'static str,
},
#[error("engine control channel closed unexpectedly: {message}")]
ControlClosed { message: String },
#[error("request `{request_id}` is already in flight")]
DuplicateRequestId { request_id: String },
#[error(
"data parallel rank {rank} is not connected to this frontend; connected ranks: {connected_ranks:?}"
)]
InvalidDataParallelRank {
rank: u32,
connected_ranks: Vec<u32>,View on GitHub (pinned to c794754062)
Solutions
- Reduce the number of large tensors per request, or raise msgpack_zero_copy_threshold so tensors stay inline in msgpack instead of becoming aux frames
- Check frame_count in the error to confirm how many aux frames were produced
- If multiple aux frames are legitimately needed, this is a known limitation of the current client stage — track the upstream implementation and update both sides together
- Align Rust and Python versions so aux-frame splitting rules match
Example fix
// before
let config = EngineCoreClientConfig { msgpack_zero_copy_threshold: 1024, .. }; // many tensors spill to aux frames
// after
let config = EngineCoreClientConfig { msgpack_zero_copy_threshold: 1 << 20, .. }; // keep tensors inline Defensive patterns
Strategy: validation
Validate before calling
fn aux_frame_count_ok(req: &mut EngineCoreRequest, threshold: usize) -> bool {
// dry-run the extraction the client performs before send
req.extract_aux_frames(threshold).len() <= 1
} Type guard
fn is_unsupported_aux_frames(e: &engine_core_client::Error) -> bool {
matches!(e, engine_core_client::Error::UnsupportedAuxFrames { .. })
} Try / catch
if let engine_core_client::Error::UnsupportedAuxFrames { frame_count } = &err {
tracing::warn!(frame_count, "too many aux frames; split request or raise zero-copy threshold");
} Prevention
- Set msgpack_zero_copy_threshold high enough that typical multimodal requests keep tensors inline
- Limit large tensors per request during this client stage
- Track upstream support for multi-frame aux transport and upgrade both sides together
When it happens
Trigger: A message arrives with more than one aux frame attached — i.e. a request containing multiple large tensors that each crossed the zero-copy threshold, or a peer that batches aux frames differently than this client accepts. The variant is currently defined in the enum as the guard for this frame-count contract on aux-frame-aware paths.
Common situations: Multimodal requests with several large embedding tensors (multiple images/video frames) each extracted into their own aux frame, exceeding the 1-frame limit of the current implementation stage. Also version mismatch if the Python side emits multiple aux frames where the Rust stage expects one.
Related errors
- transport error
- ZMQ runtime task failed
- engine core reported fatal failure
- data parallel size ({}) exceeds the two-byte engine identity
- failed to build request runtime
AI-assisted analysis of vllm-project/vllm@c794754062 (2026-08-14).
Data as JSON: /api/errors/70cbd4c1e2925129.
Report an issue: GitHub.