sgl-project/sglang · error · ValueError

BS {key}: candidate_steps must be a list of non-negative int

Error message

BS {key}: candidate_steps must be a list of non-negative ints, got {steps!r}

What it means

Validating the speculative_adaptive_config: a batch-size entry's candidate_steps field must be a non-empty list of non-negative integers. Anything else (missing key, empty list, floats, strings, negatives) is rejected.

Source

Thrown at python/sglang/srt/speculative/adaptive_spec_params.py:114

    """
    if cfg_path is not None:
        with open(cfg_path) as f:
            cfg = json.load(f)
    else:
        cfg = DEFAULT_ADAPTIVE_CONFIG

    bs_entries: dict[int, dict] = {}
    for key, entry in cfg.items():
        if not key.isdigit():
            continue

        steps = entry.get("candidate_steps")
        if (
            not isinstance(steps, list)
            or not steps
            or not all(isinstance(s, int) and s >= 0 for s in steps)
        ):
            raise ValueError(
                f"BS {key}: candidate_steps must be a list of non-negative ints, "
                f"got {steps!r}"
            )
        bs_entries[int(key)] = entry

    if not bs_entries:
        raise ValueError(
            "speculative_adaptive_config must contain at least one integer-string "
            'BS key, e.g. {"1": {"candidate_steps": [1,3,7]}}. '
            f"Got keys: {list(cfg.keys())}"
        )
    return cfg, bs_entries


def resolve_candidate_steps_from_config(
    cfg_path: str | None = None,
) -> list[int]:
    """Union of every BS slot's candidate steps; sizes the runtime buffers."""

View on GitHub (pinned to 0132848349)

Solutions

  1. Fix the entry so candidate_steps is a non-empty list of non-negative ints
  2. Validate the config JSON before passing it to the server

Example fix

# before
{"4": {"candidate_steps": [1, 3.0, "7"]}}
# after
{"4": {"candidate_steps": [1, 3, 7]}}
Defensive patterns

Strategy: type-guard

Validate before calling

def ok_steps(s):
    return isinstance(s, list) and len(s) > 0 and all(isinstance(x, int) and not isinstance(x, bool) and x >= 0 for x in s)
assert all(ok_steps(e.get('candidate_steps')) for e in cfg.values())

Type guard

def is_valid_candidate_steps(v) -> bool:
    return isinstance(v, list) and bool(v) and all(isinstance(x, int) and not isinstance(x, bool) and x >= 0 for x in v)

Prevention

When it happens

Trigger: A BS entry whose candidate_steps is absent, [], contains floats/strings/negative numbers, or is not a list at all.

Common situations: Hand-editing the adaptive config JSON and using floats (3.0), strings ("3"), or forgetting the field; YAML-to-JSON conversion artifacts.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/0c9444289e9a2bd9. Report an issue: GitHub.