vllm-project/vllm · error · ValueError
rejection_sample_method='synthetic' requires exactly one of
Error message
rejection_sample_method='synthetic' requires exactly one of synthetic_acceptance_rates or synthetic_acceptance_length.
What it means
SpeculativeConfig._resolve_synthetic_acceptance_rates requires exactly one of synthetic_acceptance_rates (explicit per-position rates) or synthetic_acceptance_length (mean accepted length, converted to rates). The check (rates is None) == (length is None) fires when both are given or neither is — the synthetic rejection-sample profile is ambiguous.
Source
Thrown at vllm/config/speculative.py:264
def _acceptance_length_to_rates(length: float, n: int) -> list[float]:
"""Mean acceptance length to unconditional per-position rates, using
the minimum-variance schedule."""
num_drafts = length - 1 # expected number of accepted draft tokens
num_full = int(num_drafts)
return (
[1.0] * num_full + [num_drafts - num_full] + [0.0] * (n - num_full - 1)
)[:n]
@staticmethod
def _resolve_synthetic_acceptance_rates(
n: int,
rates: list[float] | None,
length: float | None,
) -> list[float]:
"""Return per-position unconditional acceptance rates from exactly one
of `rates` or `length` (validates range, length, and monotonicity)."""
if (rates is None) == (length is None):
raise ValueError(
"rejection_sample_method='synthetic' requires exactly one of "
"synthetic_acceptance_rates or synthetic_acceptance_length."
)
if rates is not None:
if len(rates) != n:
raise ValueError(
f"synthetic_acceptance_rates must have length {n}, got {rates}."
)
if not all(0.0 <= r <= 1.0 for r in rates):
raise ValueError(
f"synthetic_acceptance_rates entries must be in [0, 1], "
f"got {rates}."
)
if any(rates[i] > rates[i - 1] for i in range(1, n)):
raise ValueError(
f"synthetic_acceptance_rates must be non-increasing, got {rates}."
)
return list(rates)View on GitHub (pinned to c794754062)
Solutions
- Provide exactly one of synthetic_acceptance_rates or synthetic_acceptance_length
- For a target mean accepted length use synthetic_acceptance_length (simpler); for precise per-position control use rates
- Strip the unused key from YAML/JSON overlays that may inject it
Example fix
# before SpeculativeConfig(rejection_sample_method='synthetic', synthetic_acceptance_rates=[0.9, 0.8], synthetic_acceptance_length=2.0) # after SpeculativeConfig(rejection_sample_method='synthetic', synthetic_acceptance_length=2.0)
Defensive patterns
Strategy: validation
Validate before calling
def exactly_one(rates, length) -> bool:
return (rates is None) != (length is None) Type guard
null
Try / catch
null
Prevention
- Set exactly one of the two synthetic profile keys in YAML
- Prefer synthetic_acceptance_length for simplicity
- Lint speculative config templates for the both/neither case
When it happens
Trigger: SpeculativeConfig(rejection_sample_method='synthetic') with neither rates nor length; supplying both synthetic_acceptance_rates=[...] and synthetic_acceptance_length=2.5; leftover defaults from config templates filling both fields.
Common situations: Config templating that sets 'sensible defaults' for every field; upgrading from an API that accepted either implicitly; merging YAML overlays that each contribute one of the two keys.
Related errors
- synthetic_acceptance_rates must have length {n}, got {rates}
- synthetic_acceptance_rates entries must be in [0, 1], got {r
- synthetic_acceptance_rates must be non-increasing, got {rate
- synthetic_acceptance_length must be in [1, {n + 1}], got {le
- prompt_lookup_min={self.prompt_lookup_min} must be <= prompt
AI-assisted analysis of vllm-project/vllm@c794754062 (2026-08-14).
Data as JSON: /api/errors/ba716e61c162e684.
Report an issue: GitHub.