{"record":{"id":"482dc61f5cd90073","repo":"vllm-project/vllm","slug":"engine-core-client-is-closed-message","errorCode":null,"errorMessage":"engine-core client is closed: {message}","messagePattern":"engine-core client is closed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"rust/src/engine-core-client/src/error.rs","lineNumber":80,"sourceCode":"    #[error(\"unsupported field `{field}` in {context}\")]\n    UnsupportedField {\n        context: &'static str,\n        field: &'static str,\n    },\n    #[error(\"engine control channel closed unexpectedly: {message}\")]\n    ControlClosed { message: String },\n    #[error(\"request `{request_id}` is already in flight\")]\n    DuplicateRequestId { request_id: String },\n    #[error(\n        \"data parallel rank {rank} is not connected to this frontend; connected ranks: {connected_ranks:?}\"\n    )]\n    InvalidDataParallelRank {\n        rank: u32,\n        connected_ranks: Vec<u32>,\n    },\n    #[error(\"engine-core output dispatcher closed: {message}\")]\n    DispatcherClosed { message: String },\n    #[error(\"engine-core client is closed: {message}\")]\n    ClientClosed { message: String },\n    #[error(\"request output stream for `{request_id}` closed unexpectedly\")]\n    RequestStreamClosed { request_id: String },\n    #[error(\"utility call `{method}` failed (call_id={call_id}): {message}\")]\n    UtilityCallFailed {\n        method: String,\n        call_id: UtilityCallId,\n        message: String,\n    },\n    #[error(\"utility call `{method}` returned an invalid result (call_id={call_id}): {message}\")]\n    UtilityResultDecode {\n        method: String,\n        call_id: UtilityCallId,\n        message: String,\n    },\n    #[error(\"utility call `{method}` closed unexpectedly (call_id={call_id})\")]\n    UtilityCallClosed { method: String, call_id: u64 },\n    #[error(\"utility call `{method}` returned inconsistent results across engines: {values}\")]","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/vllm-project/vllm/blob/c794754062d49a8fdb63ab3c5215b488b865030c/rust/src/engine-core-client/src/error.rs#L62-L98","documentation":"EngineCoreError::ClientClosed is returned when an operation is attempted on an EngineCoreClient that has already been shut down. The client keeps closed state after shutdown(), and any subsequent generate/abort/utility call hits this guard instead of touching dead sockets.","triggerScenarios":"Calling any API on the client after shutdown() has completed; sharing an Arc<EngineCoreClient> across tasks where one task shuts down while another still issues requests; using a client dropped from a connection pool and re-initialized to closed state.","commonSituations":"Task-join ordering bugs during graceful shutdown; a background metrics/utility task outliving the main serving loop; re-using a client after an error path already triggered shutdown.","solutions":["Audit call sites that run concurrently with shutdown and gate them with a shutdown signal/ CancellationToken","Create a new EngineCoreClient if you need to keep serving after a shutdown","Ensure background tasks (utility calls, stream consumers) are joined before calling shutdown()"],"exampleFix":"// before\nlet handle = tokio::spawn(client.clone().run_utility_loop());\nclient.shutdown().await; // background task still uses client\n\n// after\nlet handle = tokio::spawn(client.clone().run_utility_loop());\nshutdown_tx.send(()); \nhandle.await;\nclient.shutdown().await;","handlingStrategy":"validation","validationCode":"// Guard calls with a lifecycle flag\nif client.is_closed() { return Err(anyhow::anyhow!(\"client already shut down\")); }\nclient.generate(request_id, req).await","typeGuard":"pub fn is_client_closed(e: &vllm_engine_core_client::Error) -> bool {\n    matches!(e, vllm_engine_core_client::Error::ClientClosed { .. })\n}","tryCatchPattern":"match client.generate(/*..*/).await {\n    Err(e @ vllm_engine_core_client::Error::ClientClosed { .. }) => {\n        tracing::warn!(\"client closed before call; skipping: {e}\");\n        Ok(Default::default()) // or propagate as poisoned-state\n    }\n    other => other,\n}","preventionTips":["Broadcast a shutdown token; all tasks must observe it and stop calling the client before shutdown() runs","Join background utility/stream tasks before initiating client shutdown","Never reuse a client after shutdown — create a fresh one for a new engine session"],"tags":["lifecycle","shutdown","api-misuse","rust"],"backgroundTag":null,"analyzedSha":"c794754062d49a8fdb63ab3c5215b488b865030c","analyzedAt":"2026-08-14T21:17:39.825Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}