Your current environment
Relevant environment details
OS: Ubuntu 22.04.5 LTS (aarch64)
Python: 3.12.13
PyTorch: 2.10.0+cpu
vLLM: 0.25.1
The failure occurs while constructing VllmConfig, before workers or accelerator resources are initialized. I reproduced it dynamically with vLLM 0.25.1 and confirmed that vLLM main at commit 16cfe728d8d0bc3cd4a8397db0f392dd52a2c109 still has the same run_headless() ordering.
Describe the bug
vllm serve --headless does not import the file passed through --reasoning-parser-plugin before creating the engine config. If --reasoning-parser names a parser registered by that plugin, headless startup fails with KeyError.
This affects remote/headless ranks used by multi-node data-parallel deployments. It was originally observed in vLLM Ascend issue vllm-project/vllm-ascend#14573, but the failing path is in vLLM core and does not depend on the accelerator backend.
Create a minimal parser:
# /tmp/custom_reasoning_parser.py
from vllm.reasoning import ReasoningParser, ReasoningParserManager
@ReasoningParserManager.register_module("custom_headless")
class CustomHeadlessReasoningParser(ReasoningParser):
reasoning_start_str = "<think>"
reasoning_end_str = "</think>"
def extract_reasoning_streaming(self, *args, **kwargs):
return None
def extract_reasoning(self, model_output, request):
return None, model_output
Then start a headless rank. The command does not require the DP head rank to reproduce the early failure:
timeout 60s vllm serve Qwen/Qwen3-0.6B \
--headless \
--data-parallel-size 2 \
--data-parallel-size-local 1 \
--data-parallel-start-rank 1 \
--data-parallel-address 127.0.0.1 \
--data-parallel-rpc-port 29550 \
--reasoning-parser custom_headless \
--reasoning-parser-plugin /tmp/custom_reasoning_parser.py
Observed result:
File "vllm/entrypoints/cli/serve.py", line 180, in run_headless
vllm_config = engine_args.create_engine_config(
File "vllm/config/vllm.py", line 1484, in __post_init__
self.reasoning_config.initialize_token_ids(self.model_config)
File "vllm/config/reasoning.py", line 77, in initialize_token_ids
parser_cls = ReasoningParserManager.get_reasoning_parser(
File "vllm/reasoning/abs_reasoning_parsers.py", line 245, in get_reasoning_parser
raise KeyError(
KeyError: "Reasoning parser 'custom_headless' not found. Available parsers: ..."
Expected result: the plugin is imported before engine config construction, so the headless rank proceeds to worker launch/DP handshake instead of raising KeyError.
The regular API server path already has the required ordering:
# vllm/entrypoints/openai/api_server.py
if args.reasoning_parser_plugin and len(args.reasoning_parser_plugin) > 3:
ReasoningParserManager.import_reasoning_parser(args.reasoning_parser_plugin)
run_headless() instead calls AsyncEngineArgs.create_engine_config() directly. During VllmConfig.__post_init__, ReasoningConfig.initialize_token_ids() resolves the configured parser before the plugin is imported anywhere else.
As a control, explicitly calling ReasoningParserManager.import_reasoning_parser(plugin_path) before create_engine_config(headless=True) succeeds and produces an enabled reasoning config.
A narrow fix would import args.reasoning_parser_plugin in run_headless() before AsyncEngineArgs.create_engine_config(). Importing it from the StructuredOutputsConfig validator would be broader and would reintroduce the duplicate-registration/programmatic-registration problem removed by #28749.
Before submitting a new issue...
Your current environment
Relevant environment details
The failure occurs while constructing
VllmConfig, before workers or accelerator resources are initialized. I reproduced it dynamically with vLLM 0.25.1 and confirmed that vLLM main at commit16cfe728d8d0bc3cd4a8397db0f392dd52a2c109still has the samerun_headless()ordering.Describe the bug
vllm serve --headlessdoes not import the file passed through--reasoning-parser-pluginbefore creating the engine config. If--reasoning-parsernames a parser registered by that plugin, headless startup fails withKeyError.This affects remote/headless ranks used by multi-node data-parallel deployments. It was originally observed in vLLM Ascend issue vllm-project/vllm-ascend#14573, but the failing path is in vLLM core and does not depend on the accelerator backend.
Create a minimal parser:
Then start a headless rank. The command does not require the DP head rank to reproduce the early failure:
Observed result:
Expected result: the plugin is imported before engine config construction, so the headless rank proceeds to worker launch/DP handshake instead of raising
KeyError.The regular API server path already has the required ordering:
run_headless()instead callsAsyncEngineArgs.create_engine_config()directly. DuringVllmConfig.__post_init__,ReasoningConfig.initialize_token_ids()resolves the configured parser before the plugin is imported anywhere else.As a control, explicitly calling
ReasoningParserManager.import_reasoning_parser(plugin_path)beforecreate_engine_config(headless=True)succeeds and produces an enabled reasoning config.A narrow fix would import
args.reasoning_parser_plugininrun_headless()beforeAsyncEngineArgs.create_engine_config(). Importing it from theStructuredOutputsConfigvalidator would be broader and would reintroduce the duplicate-registration/programmatic-registration problem removed by #28749.Before submitting a new issue...