{"record":{"id":"03b6d12f9555fad4","repo":"vllm-project/vllm","slug":"tp-sizes-must-be-positive","errorCode":null,"errorMessage":"TP sizes must be positive","messagePattern":"TP sizes must be positive","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"vllm/distributed/kv_transfer/kv_connector/v1/moriio/moriio_connector.py","lineNumber":110,"sourceCode":"        IOEngineConfig,\n    )\n\n    logger.info(\"MoRIIO is available\")\n    MoRIIO_enabled = True\nexcept ImportError:\n    logger.error(\"MoRIIO is not available\")\n    MoRIIO_enabled = False\n\n\ndef is_moriio_available() -> bool:\n    return MoRIIO_enabled\n\n\ndef get_moriio_remote_tp_rank(\n    local_tp_rank: int, local_tp_size: int, remote_tp_size: int\n) -> int:\n    if local_tp_size <= 0 or remote_tp_size <= 0:\n        raise ValueError(\"TP sizes must be positive\")\n    if local_tp_rank < 0 or local_tp_rank >= local_tp_size:\n        raise ValueError(\n            f\"local_tp_rank {local_tp_rank} must be in [0, {local_tp_size})\"\n        )\n    if remote_tp_size == local_tp_size:\n        return local_tp_rank\n    if remote_tp_size > local_tp_size:\n        if remote_tp_size % local_tp_size != 0:\n            raise ValueError(\n                f\"remote tp_size {remote_tp_size} must be a multiple of local \"\n                f\"tp_size {local_tp_size} for heterogeneous-TP P/D\"\n            )\n        return local_tp_rank * (remote_tp_size // local_tp_size)\n    if local_tp_size % remote_tp_size != 0:\n        raise ValueError(\n            f\"local tp_size {local_tp_size} must be a multiple of remote \"\n            f\"tp_size {remote_tp_size} for heterogeneous-TP P/D\"\n        )","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/vllm-project/vllm/blob/c794754062d49a8fdb63ab3c5215b488b865030c/vllm/distributed/kv_transfer/kv_connector/v1/moriio/moriio_connector.py#L92-L128","documentation":"get_moriio_remote_tp_rank maps a local TP rank to the corresponding remote (peer) TP rank in disaggregated prefill/decode. It raises ValueError('TP sizes must be positive') when local_tp_size or remote_tp_size is zero or negative, i.e. the peer's tensor-parallel size was never configured.","triggerScenarios":"Calling get_moriio_remote_tp_rank with a tp size of 0 or a negative value; in practice the remote tp size is derived from kv_transfer_params/handshake metadata and defaults to 0 when the peer never announced it.","commonSituations":"Decode instance starts before the prefill registered its tp size; remote_tp_size config key misspelled or missing so it resolves to 0; multi-pod config lists mismatched dp/tp fields.","solutions":["Verify both instances report a valid --tensor-parallel-size (>= 1)","Check where remote_tp_size is sourced (kv_transfer_params or handshake metadata) and that the peer populates it before transfers begin","Ensure startup ordering: peer metadata handshake completes before rank mapping is attempted"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"def validate_tp_sizes(*sizes: int) -> None:\n    for s in sizes:\n        if s <= 0:\n            raise ValueError(f\"TP size must be positive, got {s}\")","typeGuard":"def are_positive_tp_sizes(*sizes) -> bool:\n    return all(isinstance(s, int) and s > 0 for s in sizes)","tryCatchPattern":null,"preventionTips":["Default remote tp size configs to a sentinel like None and reject explicitly rather than 0","Wait for peer handshake metadata before computing rank mappings"],"tags":["tensor-parallel","kv-transfer","config","validation"],"backgroundTag":null,"analyzedSha":"c794754062d49a8fdb63ab3c5215b488b865030c","analyzedAt":"2026-08-14T21:17:39.825Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}