{"record":{"id":"a9e69df6cf0f42b0","repo":"sgl-project/sglang","slug":"auxiliary-pp-output-must-contain-at-least-one-tens","errorCode":null,"errorMessage":"auxiliary PP output must contain at least one tensor","messagePattern":"auxiliary PP output must contain at least one tensor","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/sampling/sampling_observer_pp.py","lineNumber":48,"sourceCode":"\n\n_OUTPUT_PREFIX = \"__sampling_observer_output__.\"\n\n\ndef add_auxiliary_output_to_pp_tensors(\n    tensors: MutableMapping[str, Any],\n    output: Optional[DeviceAuxiliaryOutput],\n) -> None:\n    if output is None:\n        return\n    if not isinstance(output, PipelineParallelAuxiliaryOutput):\n        raise RuntimeError(\n            \"auxiliary output does not support pipeline-parallel transport\"\n        )\n\n    output_tensors = output.to_pp_tensors()\n    if not output_tensors:\n        raise RuntimeError(\"auxiliary PP output must contain at least one tensor\")\n\n    for name, tensor in output_tensors.items():\n        if not isinstance(name, str) or not name:\n            raise RuntimeError(\"auxiliary PP tensor names must be non-empty strings\")\n        if not torch.is_tensor(tensor):\n            raise RuntimeError(f\"auxiliary PP output {name!r} is not a tensor\")\n        key = f\"{_OUTPUT_PREFIX}{name}\"\n        if key in tensors:\n            raise RuntimeError(f\"duplicate auxiliary PP tensor {name!r}\")\n        tensors[key] = tensor\n\n\ndef pop_auxiliary_output_from_pp_tensors(\n    tensors: MutableMapping[str, Any],\n    observer: Optional[SamplingObserver],\n) -> Optional[DeviceAuxiliaryOutput]:\n    output_tensors = {\n        key.removeprefix(_OUTPUT_PREFIX): value","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/sampling/sampling_observer_pp.py#L30-L66","documentation":"A PipelineParallelAuxiliaryOutput serialized to zero tensors, so there is nothing to forward across pipeline stages and the transport would be a no-op the receiver can't reconstruct.","triggerScenarios":"An auxiliary output whose to_pp_tensors() returns {} or an empty mapping passed into add_auxiliary_output_to_pp_tensors.","commonSituations":"Custom auxiliary output where all fields are None/optional and to_pp_tensors filters them all out; stub implementation returning {}.","solutions":["Ensure to_pp_tensors() returns at least one tensor, or skip calling add when empty","Make from_pp_tensors consistent with the non-empty requirement","Add a guard in the caller: only attach when to_pp_tensors() is truthy"],"exampleFix":"# before\nif output is not None:\n    add_auxiliary_output_to_pp_tensors(tensors, output)\n# after\nif output is not None and output.to_pp_tensors():\n    add_auxiliary_output_to_pp_tensors(tensors, output)","handlingStrategy":"validation","validationCode":"if output is not None and not output.to_pp_tensors():\n    output = None  # nothing to forward","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Guarantee to_pp_tensors() returns non-empty mappings or handle empty upstream","Round-trip test auxiliary outputs in unit tests"],"tags":["pipeline-parallel","sampling","empty-payload","validation"],"backgroundTag":"empty-payload-validation","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}