sgl-project/sglang · error · ValueError
speculative_adaptive_config must contain at least one…
Error message
speculative_adaptive_config must contain at least one integer-string BS key, e.g. {"1": {"candidate_steps": [1,3,7]}}. Got keys: {list(cfg.keys())} What it means
Adaptive speculative decoding config validation: the config must be a mapping whose keys are batch-size (BS) integer strings (e.g. "1", "8") mapping to step configs such as {"candidate_steps": [1,3,7]}. The message lists the invalid keys that were supplied.
Solutions
- Rewrite the config with integer-string keys: {"1": {"candidate_steps": [1,3,7]}, "8": {...}}
- If loading via YAML/JSON where keys become ints, serialize to a dict with str(k) keys first
Example fix
# before
speculative_adaptive_config = {8: {"candidate_steps": [1, 3]}}
# after
speculative_adaptive_config = {"8": {"candidate_steps": [1, 3]}} Defensive patterns
Strategy: type-guard
Validate before calling
assert isinstance(cfg, dict) and cfg and all(k.isdigit() for k in cfg), f'keys must be integer strings, got {list(cfg)}' Type guard
def is_valid_bs_keys(cfg) -> bool:
return isinstance(cfg, dict) and len(cfg) > 0 and all(isinstance(k, str) and k.isdigit() for k in cfg.keys()) Prevention
- Normalize config keys with str(k) after YAML loads them as ints
- Use the documented {"1": {"candidate_steps": [...]}} shape verbatim
When it happens
Trigger: Passing an empty dict, or a dict whose keys are not integer strings (e.g. {"default": ...}, {"bs_8": ...}, or integer keys already parsed as ints by JSON/YAML loading).
Common situations: Using non-string keys in a YAML config that loads as ints; naming keys by label instead of batch size; passing the wrong structure entirely.
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
- BS : candidate_steps must be a list of non-negative ints…
- DFLASH mask_token must be a non-empty string, got
- DSpark speculative_num_draft_tokens must be >= 2 (= gamma +…
- batch_draft_token_num config value
- candidates and next_token_logits must be on the same…
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/fcbcf5eaec32af76.
Report an issue: GitHub.
Appendix: source
Thrown at python/sglang/srt/speculative/adaptive_spec_params.py:121
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."""
_, bs_entries = _load_adaptive_config(cfg_path)
all_steps: set[int] = set()
for entry in bs_entries.values():
all_steps.update(entry["candidate_steps"])
return sorted(all_steps)
View on GitHub (pinned to 0132848349)