Skip to content

[Bug]: --headless does not load custom reasoning parser plugins #53072

Description

@QwertyJack

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...

  • Make sure you already searched for relevant issues, and asked the chatbot living at the bottom right corner of the documentation page, which can answer lots of frequently asked questions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions