{"record":{"id":"8657683926625d47","repo":"vllm-project/vllm","slug":"combined-parser-is-constructed-from-split-parser-i","errorCode":null,"errorMessage":"combined parser is constructed from split parser instances","messagePattern":"combined parser is constructed from split parser instances","errorType":"exception","errorClass":"UnifiedParserError","httpStatus":null,"severity":"error","filePath":"rust/src/parser/src/unified/mod.rs","lineNumber":204,"sourceCode":"    /// Feed one decoded text delta into the parser, appending committed output into `output`.\n    fn parse_into(&mut self, delta: &str, output: &mut UnifiedParserOutput) -> Result<()>;\n\n    /// Flush any buffered parser state at end of stream.\n    fn finish(&mut self) -> Result<UnifiedParserOutput> {\n        Ok(UnifiedParserOutput::default())\n    }\n\n    /// Clear parser state and return currently uncommitted buffered text.\n    fn reset(&mut self) -> String {\n        String::new()\n    }\n}\n\n/// Errors produced while creating or running unified parsers.\n#[derive(Debug, Error, Macro)]\n#[thiserror_ext(macro(path = \"crate::unified\", mangle))]\npub enum UnifiedParserError {\n    #[error(\"combined parser is constructed from split parser instances\")]\n    CombinedParserConstructor,\n    #[error(\"tokenizer is missing unified parser token `{token}`\")]\n    MissingToken { token: String },\n    #[error(\"unified parser parsing failed: {message}\")]\n    ParsingFailed { message: String },\n    #[error(transparent)]\n    Reasoning(#[from] ReasoningError),\n    #[error(transparent)]\n    Tool(#[from] ToolParserError),\n}\n\n/// Returns the ID for the given token, or an error if it's not found.\nfn token_id(tokenizer: &dyn vllm_tokenizer::Tokenizer, token: &str) -> Result<u32> {\n    tokenizer.token_to_id(token).ok_or_else(|| UnifiedParserError::MissingToken {\n        token: token.to_string(),\n    })\n}\n","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/vllm-project/vllm/blob/c794754062d49a8fdb63ab3c5215b488b865030c/rust/src/parser/src/unified/mod.rs#L186-L222","documentation":"UnifiedParserError::CombinedParserConstructor is an API-misuse guard: a combined (unified) parser must be constructed through its own constructor that takes the tokenizer and shared configuration, not assembled from already-built split reasoning/tool parser instances. Building it from split instances would leave token IDs and delimiter state inconsistent, so the constructor rejects that path.","triggerScenarios":"Calling the combined-parser constructor with arguments that resolve to split parser instances (e.g. passing pre-built ReasoningParser/ToolParser trait objects) instead of letting it construct the unified components itself.","commonSituations":"Library users refactoring from split parsers to the unified API and passing their old parser objects; generic code that funnels any parser pair into the combined constructor.","solutions":["Construct the unified parser via its dedicated constructor taking tokenizer + names/config, not parser instances","If you already have split parsers, keep using the split (non-unified) pipeline instead of combining them"],"exampleFix":"// before\nlet p = CombinedParser::from_split(reasoning_parser, tool_parser);\n\n// after\nlet p = CombinedParser::new(&tokenizer, UnifiedParserConfig::new(\"granite\"));","handlingStrategy":"type-guard","validationCode":"// Prevent constructing the combined parser from split instances\nfn wants_unified(cfg: &ParserConfig) -> bool { cfg.reasoning == cfg.tool && !cfg.reasoning.is_empty() }\nif wants_unified(&cfg) { build_unified(&cfg).await } else { build_split(&cfg).await }","typeGuard":"fn is_combined_ctor_misuse(e: &UnifiedParserError) -> bool {\n    matches!(e, UnifiedParserError::CombinedParserConstructor)\n}","tryCatchPattern":"match CombinedParser::new(args) {\n    Err(e @ UnifiedParserError::CombinedParserConstructor) => {\n        return Err(anyhow::anyhow!(\"use the unified constructor with tokenizer + config, not split instances: {e}\"));\n    }\n    r => r?,\n}","preventionTips":["Use the dedicated unified constructor (tokenizer + family/config) and delete from_split-style call sites","If you already hold split parsers, run them as a split pipeline instead","Add a compile-time doc note and runtime guard on any constructor taking trait objects"],"tags":["unified-parser","api-misuse","constructor","rust"],"backgroundTag":null,"analyzedSha":"c794754062d49a8fdb63ab3c5215b488b865030c","analyzedAt":"2026-08-14T21:17:39.825Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}