Troubleshooting

vLLM KV Cache Too Small: Fix max_model_len Startup Failures

Fix vLLM startup errors caused by insufficient KV-cache capacity. Separate weight OOM from long-context sizing, batch concurrency and CUDA graph memory.

Approximately 6 min read

Quick fix: if vLLM loads the weights but refuses to start because KV-cache capacity is smaller than max_model_len, lower --max-model-len first. If that starts successfully, then tune --max-num-seqs, --gpu-memory-utilization, cache settings, or graph overhead for the workload you actually need.

Do not treat this as the same problem as a CUDA OOM while loading model weights. The failing stage tells you which memory budget to fix.

First classify the failing stage

Symptom Likely boundary
CUDA OOM while allocating model weights Model or other GPU processes consume too much VRAM
Weights load, then max sequence length exceeds KV capacity Context configuration versus usable KV cache
Server starts, but one long request is rejected Request length exceeds configured/model limit
Server starts, but concurrent traffic runs out of capacity Scheduling, aggregate active tokens and concurrency
CUDA graph capture fails after profiling Extra capture/workspace memory, not just the KV cache

Find the first error in startup logs. A later ‘engine core failed to start’ wrapper is rarely the most useful evidence.

Why available VRAM is smaller than the number on the box

The GPU must hold more than model weights. vLLM also needs runtime allocations, execution workspaces and, depending on configuration, CUDA graph memory. The remainder available for KV blocks is not simply:

GPU VRAM - GGUF/model file size

Model file size is not a reliable estimate for the complete live serving footprint. KV memory also depends on architecture, cache dtype, configured context, parallelism, and active workload. A single long sequence can be impossible even with modest concurrent traffic.

This is why a model that fits in VRAM may still fail to serve its advertised maximum context.

Step 1: Record the actual environment

On an NVIDIA host, inspect current GPU memory and competing processes:

nvidia-smi
python -m vllm --version
vllm serve --help

If python -m vllm --version is not supported in your installed package, use the installed package metadata instead:

python -m pip show vllm

Keep the exact model revision, quantization, GPU count, original startup command, max_model_len, and the cache-capacity error. Device visibility matters: a scheduler or CUDA_VISIBLE_DEVICES setting can change which GPUs the process actually uses.

Step 2: Reduce the maximum sequence length deliberately

The official vLLM Conserving Memory guide recommends limiting max_model_len and max_num_seqs to reduce memory use.

For a small, publicly available checkpoint, an illustrative local diagnostic launch is:

vllm serve Qwen/Qwen2.5-1.5B-Instruct \
  --host 127.0.0.1 \
  --port 8000 \
  --max-model-len 4096 \
  --max-num-seqs 2 \
  --gpu-memory-utilization 0.85

This is a starting experiment, not a guarantee that it fits any particular GPU. The model, supported flag syntax and required memory vary by vLLM version. Replace the model and numeric limits to suit your actual workload.

If the original error says the capacity is below an extreme context length, reduce --max-model-len to a supported number below the reported usable capacity and restart. The limit applies to the combined input and output tokens of a sequence, so plan to leave room for generation.

A client cannot overcome a server-side maximum length by sending fewer API retries.

Step 3: Separate one long request from many simultaneous requests

These settings solve different constraints:

If one short request works but concurrency triggers failures, investigate the second setting and real aggregate active-token usage. If even one sequence of the requested context length cannot fit, reducing concurrency alone does not magically create enough storage for that sequence.

Measure accepted requests and observed memory after each change; do not change all flags simultaneously.

Step 4: Adjust the GPU memory budget with a safety margin

A higher --gpu-memory-utilization value can sometimes leave more space for KV blocks, but it also reduces the headroom for external processes and unexpected allocations. Increasing this knob to its maximum is not a universal fix and can turn a clear capacity error into CUDA OOM.

On shared GPUs, inspect other active workloads and reserve capacity intentionally. Close unnecessary processes only when you own them and have permission to interrupt their work. Do not reset a production GPU merely to make one test pass.

Advanced vLLM versions also expose controls for explicit KV-cache sizing. Verify the exact installed CLI semantics before using them, because explicit cache-memory settings can override automatic memory planning and vary across releases.

Step 5: Test CUDA graph overhead separately

vLLM’s documented memory guide explains that CUDA graphs can consume extra GPU memory. If graph capture itself is the failing stage, --enforce-eager can be used as a diagnostic to disable CUDA graph capture:

vllm serve Qwen/Qwen2.5-1.5B-Instruct \
  --host 127.0.0.1 \
  --max-model-len 4096 \
  --max-num-seqs 2 \
  --enforce-eager

Eager execution can change performance. If it starts successfully, you have evidence that graph-capture overhead matters; you have not proven that the model can now safely handle all intended concurrent traffic. Revisit graph-capture sizes or memory configuration before production deployment.

If the initial weights do not fit, eager execution may do nothing. Choose a smaller model, an actually supported quantized artifact, or appropriate model parallelism instead.

Step 6: Verify the result at the serving API

After startup, a basic reachability check is:

curl -sS -i http://127.0.0.1:8000/v1/models

Successful model listing confirms the API is answering; it does not by itself prove long-context capacity or throughput. Then send a controlled small request, followed by requests approaching your chosen context boundary. Record input-token and output-token budget, concurrency and error types.

If /v1/models works but a chat request returns 404 model not found, this is a separate identifier problem. See vLLM 404: Fix the Served Name.

Decision summary

  1. OOM before weights finish loading: solve weight/GPU footprint first.
  2. Weights fit but KV capacity is below max_model_len: lower context or increase genuinely available KV capacity.
  3. Small requests work, high concurrency fails: limit concurrency and profile active tokens.
  4. Failure occurs in CUDA graph capture: test eager mode as an isolation control.
  5. API starts yet one request exceeds configured length: respect the combined input/output token limit.

Keep the original error, vLLM version, model identity, GPU-visible memory and one changed parameter per test. Never publish private logs, credentials or internal network topology in an issue.

Primary sources

Also see How to Reduce LLM VRAM Usage and vLLM model alias 404 troubleshooting.

Sources and further reading