sgl-project/sglang · error · ValueError

Expected batch size 1 for decoded audio, got shape={tuple(wa

Error message

Expected batch size 1 for decoded audio, got shape={tuple(waveform.shape)}

What it means

When a decoded audio waveform arrives with 3 dimensions [B, T, C], the batch dimension must be 1 because the Joy-Echo memory slot stores a single clip; a multi-clip batch cannot be saved into one memory slot. The waveform is then indexed [0] to drop the batch dim.

Source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/joy_echo/memory.py:540

    if video_uint8.shape[-1] != 3:
        raise ValueError(
            f"Expected RGB video with trailing channel dim 3, got shape={tuple(video_uint8.shape)}"
        )
    video_uint8 = video_uint8.detach().cpu().contiguous()
    return [Image.fromarray(frame.numpy()) for frame in video_uint8]


def normalize_audio_waveform_for_media(
    audio_waveform: Optional[torch.Tensor],
) -> Optional[torch.Tensor]:
    if audio_waveform is None:
        return None

    waveform = torch.as_tensor(audio_waveform).detach().cpu().float()

    if waveform.ndim == 3:
        if waveform.shape[0] != 1:
            raise ValueError(
                f"Expected batch size 1 for decoded audio, got shape={tuple(waveform.shape)}"
            )
        waveform = waveform[0]
    if waveform.ndim == 1:
        waveform = waveform.unsqueeze(0)
    elif (
        waveform.ndim == 2
        and waveform.shape[0] not in {1, 2}
        and waveform.shape[1]
        in {
            1,
            2,
        }
    ):
        waveform = waveform.transpose(0, 1)
    elif waveform.ndim != 2:
        raise ValueError(
            f"Expected decoded audio with 1, 2, or 3 dims, got shape={tuple(waveform.shape)}"

View on GitHub (pinned to 0132848349)

Solutions

  1. Index the desired clip before passing: waveform = waveform[i] or waveform[i:i+1]
  2. If generating one slot per batch item, loop over the batch and call save_memory_slot per item with audio_waveform=batch[i:i+1]
  3. Add an assert on waveform.shape[0]==1 in your own wrapper to fail with context

Example fix

# before
save_memory_slot(..., audio_waveform=batched_waveform)  # [4, T, C]
# after
for i in range(batched_waveform.shape[0]):
    save_memory_slot(..., audio_waveform=batched_waveform[i:i+1])
Defensive patterns

Strategy: validation

Validate before calling

if waveform.ndim == 3 and waveform.shape[0] != 1:
    raise ValueError(f"select a single clip before saving; batch dim is {waveform.shape[0]}")

Type guard

def is_single_clip_waveform(t: torch.Tensor) -> bool:
    return t.ndim in (1, 2) or (t.ndim == 3 and t.shape[0] == 1)

Prevention

When it happens

Trigger: Calling normalize_audio_waveform_for_media (via save_memory_slot) with a [B,T,C] tensor where B>1, e.g. a batched codec/VAE decoder output of multiple audio clips.

Common situations: Feeding batched audio-decoder output directly instead of indexing the clip you want; batch inference where each sample's audio must be saved to its own memory slot.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/271468abe3d94290. Report an issue: GitHub.