{"record":{"id":"b7ee8fa264d12819","repo":"vllm-project/vllm","slug":"synthetic-acceptance-rates-must-be-non-increasing","errorCode":null,"errorMessage":"synthetic_acceptance_rates must be non-increasing, got {rates}.","messagePattern":"synthetic_acceptance_rates must be non-increasing, got (.+?)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"vllm/config/speculative.py","lineNumber":279,"sourceCode":"        \"\"\"Return per-position unconditional acceptance rates from exactly one\n        of `rates` or `length` (validates range, length, and monotonicity).\"\"\"\n        if (rates is None) == (length is None):\n            raise ValueError(\n                \"rejection_sample_method='synthetic' requires exactly one of \"\n                \"synthetic_acceptance_rates or synthetic_acceptance_length.\"\n            )\n        if rates is not None:\n            if len(rates) != n:\n                raise ValueError(\n                    f\"synthetic_acceptance_rates must have length {n}, got {rates}.\"\n                )\n            if not all(0.0 <= r <= 1.0 for r in rates):\n                raise ValueError(\n                    f\"synthetic_acceptance_rates entries must be in [0, 1], \"\n                    f\"got {rates}.\"\n                )\n            if any(rates[i] > rates[i - 1] for i in range(1, n)):\n                raise ValueError(\n                    f\"synthetic_acceptance_rates must be non-increasing, got {rates}.\"\n                )\n            return list(rates)\n        assert length is not None\n        if not 1.0 <= length <= float(n + 1):\n            raise ValueError(\n                f\"synthetic_acceptance_length must be in [1, {n + 1}], got {length}.\"\n            )\n        return SpeculativeConfig._acceptance_length_to_rates(length, n)\n\n    draft_sample_method: DraftSampleMethod = \"greedy\"\n    \"\"\"How the draft model samples tokens. 'greedy' always picks the argmax\n    token, and the draft probabilities are treated as one-hot during rejection\n    sampling. 'probabilistic' samples stochastically from the draft\n    distribution and uses the full draft logits for the probability ratio test\n    during rejection sampling. This comes at the cost of additional GPU memory\n    usage.\"\"\"\n","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/vllm-project/vllm/blob/c794754062d49a8fdb63ab3c5215b488b865030c/vllm/config/speculative.py#L261-L297","documentation":"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.","triggerScenarios":"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.","commonSituations":"Empirical profiling without smoothing; accidental ascending sort of the rate list.","solutions":["Sort descending: rates = sorted(rates, reverse=True)","Smooth noisy measurements (e.g. running minimum: rates = np.minimum.accumulate(rates))","Or fall back to synthetic_acceptance_length, which always yields a monotone profile"],"exampleFix":"# before\nsynthetic_acceptance_rates=[0.7, 0.75, 0.6]\n\n# after\nsynthetic_acceptance_rates=[0.75, 0.7, 0.6]","handlingStrategy":"validation","validationCode":"def rates_monotone(rates: list[float]) -> bool:\n    return all(rates[i] <= rates[i-1] for i in range(1, len(rates)))","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Apply running-minimum smoothing to empirical profiles","Sort descending before passing","Fall back to synthetic_acceptance_length when monotonicity is uncertain"],"tags":["speculative-decoding","config","validation","math"],"backgroundTag":null,"analyzedSha":"c794754062d49a8fdb63ab3c5215b488b865030c","analyzedAt":"2026-08-14T21:17:39.825Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}