sgl-project/sglang · error · ValueError

keyframe condition rows require plan.task='fl2va' or 'ref2va

Error message

keyframe condition rows require plan.task='fl2va' or 'ref2va'

What it means

At the DiT sink, _validate_keyframe_payload rejects any non-None keyframe payload when plan.task is not 'fl2va' or 'ref2va'. Keyframe conditioning is only meaningful for those two tasks.

Source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/stages/denoising.py:86

        # imgvid noise aug 1.0 still overrides this.
        imgvid_noise_aug = MINIMAX_H3_IMGVID_COND_TIMESTEP
    audio_noise_aug = getattr(
        sampling,
        "audio_cond_noise_aug_for_inference",
        None,
    )
    if audio_noise_aug is None:
        audio_noise_aug = MINIMAX_H3_AUDIO_REF_COND_TIMESTEP
    return float(imgvid_noise_aug), float(audio_noise_aug)


def _validate_keyframe_payload(plan: Any, keyframe: Any) -> None:
    """Reject stale/middle/reordered keyframe payloads at the DiT sink."""

    task = None if plan is None else str(plan.task)
    if task not in {"fl2va", "ref2va"}:
        if keyframe is not None:
            raise ValueError(
                "keyframe condition rows require plan.task='fl2va' or 'ref2va'"
            )
        return
    if keyframe is None:
        if task == "fl2va":
            raise ValueError("fl2va denoising requires encoded keyframe condition rows")
        return
    if not isinstance(keyframe, Mapping):
        raise ValueError("encoded keyframe condition rows must be a mapping")

    semantic_indices = tuple(keyframe.get("semantic_frame_indices") or ())
    if semantic_indices not in MINIMAX_H3_FL2VA_KEYFRAME_SIGNATURES:
        raise ValueError(
            "keyframe denoising requires semantic_frame_indices in "
            f"{MINIMAX_H3_FL2VA_KEYFRAME_SIGNATURES!r}, "
            f"got {semantic_indices!r}"
        )
    frame_count = keyframe.get("frame_count")

View on GitHub (pinned to 0132848349)

Solutions

  1. Clear keyframe payload/batch extras when switching to a non-keyframe task
  2. Set the correct task ('fl2va'/'ref2va') if keyframe conditioning was intended

Example fix

# before
batch.keyframe = old_keyframe_rows  # task is 't2v'
# after
batch.keyframe = None  # non-keyframe task
Defensive patterns

Strategy: validation

Validate before calling

if plan.task not in {"fl2va", "ref2va"}:
    batch.keyframe = None

Type guard

def keyframe_allowed(task: str) -> bool:
    return task in {"fl2va", "ref2va"}

Prevention

When it happens

Trigger: A batch carrying encoded keyframe rows (e.g. from a prior keyframe-conditioned request) reaching the denoiser while plan.task is something like 't2v'.

Common situations: Reusing a batch/request object across tasks without clearing keyframe extras; task override at decode time dropping the plan's task while stale keyframe state remains.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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