vllm-project/vllm · error · ValueError
a model must have at least one layer
Error message
a model must have at least one layer
What it means
ModelArchitectureConfig.from_layers merges per-layer configs into a whole-model config; an empty layer list has nothing to merge, so it fails fast with ValueError instead of producing a meaningless config.
Source
Thrown at vllm/config/model_arch.py:108
layer = copy(self)
object.__setattr__(layer, "per_layer_overrides", None)
for name, value in self.per_layer_overrides[layer_idx].items():
object.__setattr__(layer, name, value)
return layer
@classmethod
def from_layers(
cls, layers: "list[ModelArchitectureConfig]"
) -> "ModelArchitectureConfig":
"""Whole-model config for a checkpoint whose layers differ.
Fields that agree across layers are taken as they are. Fields that differ
are collapsed with `max`, so buffers are sized for the largest layer, and
the differing values are kept per layer. No field is named here: which
ones vary is whatever the checkpoint says.
"""
if not layers:
raise ValueError("a model must have at least one layer")
merged: dict[str, Any] = {}
overrides: list[dict[str, Any]] = [{} for _ in layers]
for f in dataclass_fields(cls):
if f.name == "per_layer_overrides":
continue
values = [getattr(layer, f.name) for layer in layers]
if all(value == values[0] for value in values):
merged[f.name] = values[0]
continue
# `bool` is an `int`, so an exact type check is what keeps a varying
# flag from collapsing to `any`. `is_deepseek_mla` doing that would
# make `use_mla` true model wide, and `get_num_kv_heads` then returns
# 1 for every layer, discarding the overrides built here.
if not all(type(value) in (int, float) for value in values):
raise ValueError(
f"{f.name!r} varies across layers and has no whole-model "
f"value: {sorted(set(map(repr, values)))}. Only numeric "View on GitHub (pinned to c794754062)
Solutions
- Debug why zero layers were collected before from_layers is called (inspect the state dict keys / layer filter).
- Guard the caller: skip construction or raise a clearer upstream error when the layer list is empty.
Example fix
# before model_arch_cfg = ModelArchitectureConfig.from_layers(layer_cfgs) # layer_cfgs == [] # after assert layer_cfgs, 'no decoder layers found in checkpoint' model_arch_cfg = ModelArchitectureConfig.from_layers(layer_cfgs)
Defensive patterns
Strategy: validation
Validate before calling
def build_from_layers(layer_cfgs):
if not layer_cfgs:
raise ValueError('checkpoint yielded zero layer configs; extraction is broken')
return ModelArchitectureConfig.from_layers(layer_cfgs) Type guard
def has_layers(layers: list) -> bool:
return len(layers) > 0 Prevention
- Never call from_layers without asserting a non-empty layer list.
- Unit-test layer extraction against real checkpoint indexes so filters never match zero layers.
- Treat an empty extraction result as a bug in the extractor, not a valid edge case.
When it happens
Trigger: Calling ModelArchitectureConfig.from_layers([]) — typically from layer-splitting logic that filtered out every layer (bad layer-type predicate, empty checkpoint state dict, or a parsing step that yielded zero layer configs).
Common situations: Custom heterogeneous-layer checkpoints where the layer extraction regex/filter matches nothing after a config schema change; tooling that builds ModelArchitectureConfig from safetensors indexes getting an empty index.
Related errors
- {f.name!r} varies across layers and has no whole-model value
- got {len(layers)} per-layer configs for a model with {merged
- Unexpected socket type: {socket_type}
- HTTP request failed: {0}
- this model's maximum context length is {max_model_len} token
AI-assisted analysis of vllm-project/vllm@c794754062 (2026-08-14).
Data as JSON: /api/errors/a8ebeb838c4d35b5.
Report an issue: GitHub.