{"record":{"id":"fda54399e0de6821","repo":"vllm-project/vllm","slug":"allowed-token-ids-should-not-be-empty","errorCode":null,"errorMessage":"allowed_token_ids should not be empty","messagePattern":"allowed_token_ids should not be empty","errorType":"validation","errorClass":"TokenIdsError","httpStatus":400,"severity":"error","filePath":"rust/src/text/src/lower/token_ids.rs","lineNumber":13,"sourceCode":"// SPDX-License-Identifier: Apache-2.0\n// SPDX-FileCopyrightText: Copyright contributors to the vLLM project\n\nuse std::result::Result;\n\nuse thiserror::Error;\nuse vllm_engine_core_client::protocol::sampling::EngineCoreSamplingParams;\n\nuse crate::SamplingLimits;\n\n#[derive(Debug, Error)]\npub enum TokenIdsError {\n    #[error(\"allowed_token_ids should not be empty\")]\n    EmptyAllowedTokenIds,\n    #[error(\n        \"token_id(s) {token_ids:?} in {parameter} are out of vocabulary. \\\n         Vocabulary size: {vocab_size}\"\n    )]\n    OutOfVocab {\n        parameter: &'static str,\n        token_ids: Vec<u32>,\n        vocab_size: usize,\n    },\n}\n\nfn validate_param(\n    parameter: &'static str,\n    token_ids: impl IntoIterator<Item = u32>,\n    vocab_size: usize,\n) -> Result<(), TokenIdsError> {\n    let invalid_token_ids: Vec<_> = token_ids","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/vllm-project/vllm/blob/c794754062d49a8fdb63ab3c5215b488b865030c/rust/src/text/src/lower/token_ids.rs#L1-L31","documentation":"`allowed_token_ids` (grammar-style token whitelist) was supplied as an empty list; the frontend rejects it in rust/src/text/src/lower/token_ids.rs:73 because an empty whitelist would make generation impossible (no token is ever allowed).","triggerScenarios":"Sending `allowed_token_ids: []` — typically a client that builds the list by filtering tokens and the filter matched nothing.","commonSituations":"Dynamic construction of a token whitelist from vocabulary lookups where all words are out-of-vocab; 'disable by emptying' patterns; default-initialized arrays sent unconditionally.","solutions":["Omit allowed_token_ids (or send null) when you do not want a whitelist","If building it dynamically, fall back to omitting the field when the filtered list is empty"],"exampleFix":"// before\nreq.allowed_token_ids = Some(matching_ids); // possibly empty\n\n// after\nreq.allowed_token_ids = matching_ids.is_empty().then_none().or(Some(matching_ids));\n// simpler: only set when non-empty\nif !matching_ids.is_empty() { req.allowed_token_ids = Some(matching_ids); }","handlingStrategy":"validation","validationCode":"if let Some(ids) = &request.allowed_token_ids {\n    assert!(!ids.is_empty(), \"allowed_token_ids must be non-empty when set\");\n}","typeGuard":"fn is_empty_allowed(e: &Error) -> bool {\n    matches!(e, Error::TokenIds(TokenIdsError::EmptyAllowedTokenIds))\n}","tryCatchPattern":"match err {\n    Error::TokenIds(TokenIdsError::EmptyAllowedTokenIds) =>\n        bad_request(\"omit allowed_token_ids instead of sending []\"),\n    _ => /* ... */\n}","preventionTips":["Only attach allowed_token_ids when the dynamically built list is non-empty","Treat empty whitelist as 'unset', never as 'allow nothing'"],"tags":["rust","validation","token-ids","vllm"],"backgroundTag":null,"analyzedSha":"c794754062d49a8fdb63ab3c5215b488b865030c","analyzedAt":"2026-08-14T21:17:39.825Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}