Found while wiring KV-EVENTS W3 (#352); filing separately rather than fixing it inside that change.
Upstream vllm/config/kv_events.py:50-52:
def __post_init__(self):
if self.publisher is None:
self.publisher = "zmq" if self.enable_kv_cache_events else "null"
publisher defaults to None (kv_events.py:19), so a user who writes --kv-events-config '{"enable_kv_cache_events": true}' and nothing else gets the zmq publisher.
Our port (include/vllm/distributed/kv_events.h:144-155) is a plain struct with std::string publisher; — an empty default — and no PostInit() anywhere. EventPublisherFactory::create (src/vllm/distributed/kv_events.cpp:319-339) therefore falls through both branches and raises:
EventPublisherFactory: unknown event publisher ''
Two things are wrong with that:
- It is not upstream's behaviour. The equivalent config selects
zmq upstream. Ours should reach the deliberately loud deferral message that already exists two lines earlier ("the 'zmq' publisher (live socket transport) is not yet ported…"), which tells the operator exactly what is going on. Instead they get a message implying they typed a bad publisher name, when they typed nothing at all.
- The header already documents the resolution as ported.
kv_events.h:146-147 says __post_init__ resolves an empty value to "zmq" when events are enabled, else "null" — but no code does it. The comment and the tree disagree.
Note the disabled case is masked by luck, not correctness: create short-circuits on !enable_kv_cache_events before it ever looks at publisher, so enable=false, publisher="" happens to yield a NullEventPublisher — the right answer for the wrong reason.
Fix
Give KVEventsConfig a PostInit() mirroring kv_events.py:50-52, call it wherever a config is built from CLI/API input, and gate it: {enable=true, publisher=""} must produce the zmq deferral throw, and {enable=false, publisher=""} must produce a NullEventPublisher.
Workaround until then
Set publisher explicitly. KV-EVENTS W3's tests pass publisher = "null" for exactly this reason, with the deferral recorded at the call site.
Found while wiring
KV-EVENTSW3 (#352); filing separately rather than fixing it inside that change.Upstream
vllm/config/kv_events.py:50-52:publisherdefaults toNone(kv_events.py:19), so a user who writes--kv-events-config '{"enable_kv_cache_events": true}'and nothing else gets the zmq publisher.Our port (
include/vllm/distributed/kv_events.h:144-155) is a plain struct withstd::string publisher;— an empty default — and noPostInit()anywhere.EventPublisherFactory::create(src/vllm/distributed/kv_events.cpp:319-339) therefore falls through both branches and raises:Two things are wrong with that:
zmqupstream. Ours should reach the deliberately loud deferral message that already exists two lines earlier ("the 'zmq' publisher (live socket transport) is not yet ported…"), which tells the operator exactly what is going on. Instead they get a message implying they typed a bad publisher name, when they typed nothing at all.kv_events.h:146-147says__post_init__resolves an empty value to "zmq" when events are enabled, else "null" — but no code does it. The comment and the tree disagree.Note the disabled case is masked by luck, not correctness:
createshort-circuits on!enable_kv_cache_eventsbefore it ever looks atpublisher, soenable=false, publisher=""happens to yield aNullEventPublisher— the right answer for the wrong reason.Fix
Give
KVEventsConfigaPostInit()mirroringkv_events.py:50-52, call it wherever a config is built from CLI/API input, and gate it:{enable=true, publisher=""}must produce the zmq deferral throw, and{enable=false, publisher=""}must produce aNullEventPublisher.Workaround until then
Set
publisherexplicitly.KV-EVENTSW3's tests passpublisher = "null"for exactly this reason, with the deferral recorded at the call site.