vLLM returns 500 on every request after the EngineCore process dies
The vLLM V1 API server survives while the separate EngineCore subprocess that owns the model does not. Once that child is gone the server keeps accepting connections and answers every one of them with an internal error until it is restarted, so an outage presents as a healthy-looking process serving nothing.
EngineDeadError names the discovery, not the cause. Read the first worker or engine-core traceback printed ABOVE it, and check dmesg for an out-of-memory kill, which leaves no traceback at all.
- Symptom
ERROR: Engine core proc EngineCore_DP0 died unexpectedly, shutting down client.- Root cause
- EngineDeadError is a bereavement notice, not a diagnosis. The API server process discovers the child is gone when it next awaits output, and reports that discovery. The exception that actually killed the engine was raised inside the EngineCore subprocess and printed to its own stream earlier, which is what the message means by see stack trace above.
- Recommended fix
VLLM_LOGGING_LEVEL=DEBUG- How Denpex helps
- Denpex matches vLLM returns 500 on every request after the EngineCore process dies across every rank in a distributed run and reports which rank failed first, so you act on the initiating node instead of the loudest one.
What this failure is
An outage mode specific to vLLM's split-process design, in which the model-owning EngineCore subprocess terminates while the HTTP server that fronts it continues running and answering requests with internal errors.
Is this what broke your run? Paste your log.
You're reading about vLLM returns 500 on every request after the EngineCore process dies. Paste your own crash log or traceback below and get the real root cause for YOUR run, not this generic entry. No account, no card. Logs are masked at ingress and never saved to account history.
Why it happens (the mechanism)
vLLM V1 puts the model in its own process so the HTTP layer stays responsive. The consequence is that the two can fail independently. When the child dies, the parent finds out only when it next awaits output, and all it can honestly say is that the engine is gone. Nothing in that message distinguishes a missing CUDA kernel from a stalled worker from a subprocess reaped by the kernel, because the parent never saw any of them happen.
What you'll observe
- Every completion request returns HTTP 500 while the container stays up and the port stays open
- A liveness probe that only checks the port keeps the dead instance in the load balancer
- The error the server reports names no cause, so there is nothing obvious to act on
- Restarting clears it for a while and it returns under the same conditions
Common symptoms and what they mean
| Symptom | Why it happens |
|---|---|
| vllm.v1.engine.exceptions.EngineDeadError: EngineCore encountered an issue. See stack trace (above) for the root cause. | EngineDeadError is a bereavement notice, not a diagnosis. The API server process discovers the child is gone when it next awaits output, and reports that discovery. The exception that actually killed the engine was raised inside the EngineCore subprocess and printed to its own stream earlier, which is what the message means by see stack trace above. |
| Engine core proc EngineCore_DP0 died unexpectedly, shutting down client | The child dies for reasons that share nothing but their effect. Reported causes include kernels that do not exist for the device, where a quantized build raises CUDA error no kernel image is available for execution on the device on the first request; an execute_model remote call timing out against a stalled worker; the kernel out-of-memory killer reaping the subprocess under load; and shared-memory limits breaking worker startup. |
| Traceback through output_handler, await engine_core.get_output_async, core_client.py get_output_async | The failure is durable because nothing restarts the engine. The parent has no model of its own to fall back on, so it stays alive serving errors, and a port-based liveness probe cannot tell that apart from a working server. |
| AsyncEngineDeadError: Background loop has errored already on the older V0 engine | EngineDeadError is a bereavement notice, not a diagnosis. The API server process discovers the child is gone when it next awaits output, and reports that discovery. The exception that actually killed the engine was raised inside the EngineCore subprocess and printed to its own stream earlier, which is what the message means by see stack trace above. |
| POST /v1/chat/completions HTTP/1.1 500 Internal Server Error repeating for every subsequent request | The child dies for reasons that share nothing but their effect. Reported causes include kernels that do not exist for the device, where a quantized build raises CUDA error no kernel image is available for execution on the device on the first request; an execute_model remote call timing out against a stalled worker; the kernel out-of-memory killer reaping the subprocess under load; and shared-memory limits breaking worker startup. |
Which systems are affected
- vLLM V1, where the API server and EngineCore are separate processes
- Containers whose health check tests only TCP reachability rather than a real completion
- Deployments using VLLM_WORKER_MULTIPROC_METHOD=spawn
- Any autoscaled fleet, where one dead replica silently absorbs its share of traffic
How to confirm this is the problem
Use this checklist to test the hypothesis against a small reproduction. No single line proves the root cause, so preserve the preceding events and compare one variable at a time.
- ✓Search the log backwards from the EngineDeadError for the first traceback attributed to a worker or engine-core process; that is the cause and it will name a device, a memory limit or a timeout.
- ✓Run dmesg -T | tail and look for an out-of-memory kill naming a Python process at the time of the failure. A kill leaves no application traceback.
- ✓Issue a one-token completion against the instance. If it returns 500 while the port accepts connections, the engine is dead and the process needs restarting rather than investigating live.
Root cause
- EngineDeadError is a bereavement notice, not a diagnosis. The API server process discovers the child is gone when it next awaits output, and reports that discovery. The exception that actually killed the engine was raised inside the EngineCore subprocess and printed to its own stream earlier, which is what the message means by see stack trace above.
- The child dies for reasons that share nothing but their effect. Reported causes include kernels that do not exist for the device, where a quantized build raises CUDA error no kernel image is available for execution on the device on the first request; an execute_model remote call timing out against a stalled worker; the kernel out-of-memory killer reaping the subprocess under load; and shared-memory limits breaking worker startup.
- The failure is durable because nothing restarts the engine. The parent has no model of its own to fall back on, so it stays alive serving errors, and a port-based liveness probe cannot tell that apart from a working server.
The fix and how to prevent it
Searchable error signature
ERROR: Engine core proc EngineCore_DP0 died unexpectedly, shutting down client.
vllm.v1.engine.exceptions.EngineDeadError: EngineCore encountered an issue. See stack trace (above) for the root cause.
INFO: 10.0.4.19:52344 - "POST /v1/chat/completions HTTP/1.1" 500 Internal Server ErrorUse this text as a lookup key in logs and upstream issue trackers. It is not presented as a captured customer log. Confirm the cause from your own preceding events, versions, configuration and the cited references.
The fix and the prevention pattern
The root cause is on this page and stays free. A free account adds the exact remediation steps, saved history, and the fix on every entry in the encyclopedia.
Sign up free. Unlock the full analysisNo credit card. Daily allowance follows verified trust tier. Instant access.
Why the recommended fix works
Reading upward finds the exception raised where the failure actually occurred, which names a device, a limit or a timeout and therefore points at a specific change. Replacing the liveness probe fixes the second half of the problem: it converts a permanent silent outage into a restart, so a cause you have not diagnosed yet still stops costing traffic while you diagnose it.
Best practices by model family
| Model / Stack | Recommendation | Notes |
|---|---|---|
| Dies on the first request | Check kernel support for the device and quantization format | A missing kernel image raises before any load-dependent condition can exist. |
| Dies under sustained load | Check dmesg for an out-of-memory kill, then lower --max-num-seqs | A kernel kill leaves no traceback, so the log alone looks like an unexplained death. |
| Dies during worker startup with tensor parallelism | Raise container shared memory or use host IPC | Worker IPC fails before the engine ever serves a request. |
| Any production deployment | Liveness probe issues a real completion | A port check cannot distinguish a dead engine from a healthy one. |
With the fix vs without the fix
| Dimension | With the fix | Without the fix |
|---|---|---|
| What EngineDeadError tells you | That the child process is gone | Assumed to be the root cause itself |
| Where the real error lives | In the EngineCore or worker output, above the message | Assumed to be absent because the message names no cause |
| Effect of a port-based health check | Dead replica keeps receiving traffic | Assumed the orchestrator will restart it |
Diagnostic note
“The most commonly misdiagnosed variant is the one with no Python traceback anywhere. When the kernel out-of-memory killer reaps the subprocess, there is nothing above the EngineDeadError to read, and the absence of a cause gets reported upstream as a vLLM bug. Check dmesg before opening an issue; host memory pressure from a large tokenizer batch or a co-located process is a frequent culprit and has nothing to do with GPU memory.”
Visual fingerprint
client -> API server process -> EngineCore process -> GPU
(alive) (dead)
| |
| +-- real traceback printed HERE, earlier
+-- EngineDeadError + HTTP 500 printed here, laterDiagnose this failure in VS Code
Select the traceback or open the failed terminal, then run Denpex locally to see the initiating rank, collateral failures, exact fix, and verification command without uploading the log.
Install the free VS Code extensionvLLM errors in context
vLLM failures cross request, model, KV cache, worker, kernel and host boundaries. The hub compares common literal signatures and the first control that separates their causal owners.
Compare every vllm error side by sideRelated failures to investigate next
Frequently asked questions
Questions engineers and on-call staff commonly ask about this failure.
The error says to see the stack trace above, but there is nothing above it.
Why does the server keep returning 500 instead of exiting?
It only happens under load. Is that a vLLM bug?
How do I stop a dead instance from receiving traffic?
References
- ↗vLLM issue #27557: engine core proc EngineCore_DP0 died unexpectedly, shutting down client
- ↗vLLM issue #22414: EngineDeadError deploying GPT-OSS-20B, caused by a missing kernel image
- ↗vLLM issue #17965: TimeoutError on an execute_model RPC preceding the EngineCore failure
- ↗vLLM issue #27194: EngineDeadError during a high-concurrency benchmark
- ↗vLLM troubleshooting guide
Don't just read the fix, diagnose your run
The encyclopedia tells you what went wrong. Denpex tells you what went wrong in YOUR training run. With your logs, your config, and your stack.
Related Reliability errors
GB200 NVL72 driver hang with Xid 150 and 154 after long uptime is a firmware bug, not a dead GPU
Reliability · high
Sequence Length Imbalance Causing Distributed Training Stragglers
Reliability · high
Silent Data Corruption from GPU Hardware Faults Causing Loss Spikes and Model Divergence
Reliability · critical
NIXL Firmware Page Registration Fan-Out Triggers Host OOM Kills on HGX H200 and B200
Reliability · critical