sgl-project/sglang · error · ValueError

condition_video_keep must be 'first' or 'last', got {keep!r}

Error message

condition_video_keep must be 'first' or 'last', got {keep!r}

What it means

When conditioning on a video, Cosmos3 keeps either the first or last frame(s) as the condition anchor, selected by sampling_params.condition_video_keep. Only "first" and "last" are valid; anything else (including a misspelled value) is rejected before latent locking.

Source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/cosmos3.py:208

                tensors.append(_pil_to_normalized_tensor(image))
            batch.preprocessed_image = torch.stack(tensors, dim=0).contiguous()
            self.log_info(
                f"Preprocessed {len(tensors)} conditioning image(s) to "
                f"{target_w}x{target_h}"
            )
            return batch

        if isinstance(video_path, str) and video_path:
            frames = load_video(video_path)
            if not frames:
                raise ValueError(f"No frames decoded from video: {video_path!r}")

            keep = (
                getattr(batch.sampling_params, "condition_video_keep", "first")
                or "first"
            )
            if keep not in ("first", "last"):
                raise ValueError(
                    f"condition_video_keep must be 'first' or 'last', got {keep!r}"
                )
            cond_indexes = self._resolve_condition_indexes(batch)
            # Encode the full output-length video so that the latent positions
            # we lock match what the decoder will reconstruct at those frame
            # indices. Encoding only the first ``max_idx*4+1`` frames produces
            # an out-of-distribution latent for the locked slots and decodes
            # to noise.
            num_source_frames = max(cond_indexes) * 4 + 1
            num_target_frames = batch.num_frames
            if keep == "last":
                frames = frames[-num_source_frames:]
            else:
                frames = frames[:num_source_frames]
            if len(frames) < num_source_frames:
                frames = frames + [frames[-1]] * (num_source_frames - len(frames))
            if len(frames) < num_target_frames:
                frames = frames + [frames[-1]] * (num_target_frames - len(frames))

View on GitHub (pinned to 0132848349)

Solutions

  1. Set condition_video_keep to "first" or "last" (lowercase) in sampling_params, or omit it to default to "first"
  2. Validate the value client-side before sending the request

Example fix

# before
sampling_params = {"condition_video_keep": "middle"}
# after
sampling_params = {"condition_video_keep": "first"}
Defensive patterns

Strategy: validation

Validate before calling

keep = sampling_params.get("condition_video_keep", "first")
assert keep in ("first", "last"), f"bad condition_video_keep: {keep!r}"

Type guard

def is_valid_keep(v) -> bool:
    return v in ("first", "last")

Prevention

When it happens

Trigger: Setting batch.sampling_params.condition_video_keep to a value other than "first"/"last" in a V2V request — e.g. "middle", "First" (case-sensitive), or "none".

Common situations: Client configs ported from other pipelines that use different keep-modes; typos or casing mistakes; JSON configs where the field is silently misspelled and getattr falls through to the raw string.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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