vllm-project/vllm · error · ValueError

Override for {field_path} must be a mapping or {expected_typ

Error message

Override for {field_path} must be a mapping or {expected_type_name}, got {type(value).__name__}

What it means

When an override targets a field whose current value is a nested dataclass, _update_config requires the override value to be either a Mapping (to recursively patch the nested config) or an instance of the field's declared type. Anything else (e.g. a plain string, int, or list) is rejected with this message naming the expected type and the actual type received. This prevents accidentally replacing a structured sub-config with an incompatible primitive.

Source

Thrown at vllm/config/utils.py:257

    for field_name, value in overrides.items():
        field_path = f"{config_path}.{field_name}"
        if not hasattr(config, field_name):
            raise ValueError(f"{field_path} is not a valid config field")

        current_value = getattr(config, field_name)
        if is_dataclass(current_value):
            expected_type = field_types[field_name]
            if isinstance(value, Mapping):
                value = _update_config(
                    current_value,  # type: ignore[type-var]
                    value,
                    field_path,
                )
            elif not isinstance(value, expected_type):
                expected_type_name = getattr(
                    expected_type, "__name__", str(expected_type)
                )
                raise ValueError(
                    f"Override for {field_path} must be a mapping or "
                    f"{expected_type_name}, got {type(value).__name__}"
                )

        processed_overrides[field_name] = value
    return replace(config, **processed_overrides)


def normalize_value(x):
    """Return a stable, JSON-serializable canonical form for hashing.
    Order: primitives, special types (Enum, callable, torch.dtype, Path), then
    generic containers (Mapping/Set/Sequence) with recursion.
    """
    # Fast path
    if x is None or isinstance(x, (bool, int, float, str)):
        return x

    # Enums: tag with FQN to avoid primitive collisions.

View on GitHub (pinned to c794754062)

Solutions

  1. Pass a nested mapping so it recurses: update_config(cfg, {'cache_config': {'gpu_memory_utilization': 0.9}})
  2. Or construct/replace with a full instance of the declared dataclass type if you have one
  3. Check get_type_hints(type(config))[field_name] (or dataclasses.fields) to confirm the expected type before sending the override

Example fix

# before
update_config(cfg, {"compilation_config": "FULL"})
# after
update_config(cfg, {"compilation_config": {"mode": "FULL"}})
Defensive patterns

Strategy: type-guard

Validate before calling

import dataclasses
from collections.abc import Mapping
from typing import get_type_hints
def check_override_types(config, overrides):
    hints = get_type_hints(type(config))
    for k, v in overrides.items():
        cur = getattr(config, k, None)
        if cur is not None and dataclasses.is_dataclass(cur):
            assert isinstance(v, Mapping) or isinstance(v, type(cur)), \
                f"{k} must be a mapping or {type(cur).__name__}"

Type guard

def overrides_well_typed(config, overrides: dict) -> bool:
    hints = get_type_hints(type(config))
    for k, v in overrides.items():
        cur = getattr(config, k, None)
        if dataclasses.is_dataclass(cur) and not (
                isinstance(v, Mapping) or isinstance(v, hints.get(k, type(cur)))):
            return False
    return True

Prevention

When it happens

Trigger: Calling update_config with something like {'parallel_config': 4} or {'compilation_config': 'FULL'} where the field holds a ParallelConfig/CompilationConfig dataclass; passing a scalar where the declared field type is a dataclass and the value is neither a dict nor that dataclass type.

Common situations: Assuming override values are always scalars and writing shorthand like {'cache_config': 2048}; CLI --config-update JSONs that flatten nested settings into dotted-strings instead of nested objects; version changes that converted a formerly-scalar field into a dataclass.

Related errors


AI-assisted analysis of vllm-project/vllm@c794754062 (2026-08-14). Data as JSON: /api/errors/14089707db7e1484. Report an issue: GitHub.