vllm-project/vllm · error · ValueError

synthetic_acceptance_rates must be non-increasing, got {rate

Error message

synthetic_acceptance_rates must be non-increasing, got {rates}.

What it means

synthetic_acceptance_rates must be non-increasing: position i+1 can only be accepted after position i is, so the unconditional acceptance probability cannot rise with depth. Any list where some rates[i] > rates[i-1] is physically inconsistent for rejection sampling and is rejected.

Source

Thrown at vllm/config/speculative.py:279

        """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)
        assert length is not None
        if not 1.0 <= length <= float(n + 1):
            raise ValueError(
                f"synthetic_acceptance_length must be in [1, {n + 1}], got {length}."
            )
        return SpeculativeConfig._acceptance_length_to_rates(length, n)

    draft_sample_method: DraftSampleMethod = "greedy"
    """How the draft model samples tokens. 'greedy' always picks the argmax
    token, and the draft probabilities are treated as one-hot during rejection
    sampling. 'probabilistic' samples stochastically from the draft
    distribution and uses the full draft logits for the probability ratio test
    during rejection sampling. This comes at the cost of additional GPU memory
    usage."""

View on GitHub (pinned to c794754062)

Solutions

  1. Sort descending: rates = sorted(rates, reverse=True)
  2. Smooth noisy measurements (e.g. running minimum: rates = np.minimum.accumulate(rates))
  3. Or fall back to synthetic_acceptance_length, which always yields a monotone profile

Example fix

# before
synthetic_acceptance_rates=[0.7, 0.75, 0.6]

# after
synthetic_acceptance_rates=[0.75, 0.7, 0.6]
Defensive patterns

Strategy: validation

Validate before calling

def rates_monotone(rates: list[float]) -> bool:
    return all(rates[i] <= rates[i-1] for i in range(1, len(rates)))

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Profiles built from independent per-position measurements with noise (e.g. [0.7, 0.75, 0.6]); monotonicity broken by rounding/clipping steps; arrays sorted ascending by mistake.

Common situations: Empirical profiling without smoothing; accidental ascending sort of the rate list.

Related errors


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