sgl-project/sglang · error · ValueError

SANA-WM streaming CFG requires negative prompt embeds.

Error message

SANA-WM streaming CFG requires negative prompt embeds.

What it means

When CFG is active in streaming (do_cfg True), negative prompt embeds (pcfg.get_neg_prompt_embeds) are mandatory. Their absence means the unconditional branch of guidance cannot be computed, so the stage raises before denoising.

Source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/sana_wm/streaming.py:477

            dtype=target_dtype,
        )
        pos_mask = _to_device_dtype(
            _first_tensor(batch.prompt_attention_mask), device=device
        )
        if pos_embeds is None:
            raise ValueError("SANA-WM streaming requires positive prompt embeds.")
        neg_embeds = neg_mask = None
        if do_cfg:
            neg_embeds = _to_device_dtype(
                _first_tensor(pcfg.get_neg_prompt_embeds(batch)),
                device=device,
                dtype=target_dtype,
            )
            neg_mask = _to_device_dtype(
                _first_tensor(batch.negative_attention_mask), device=device
            )
            if neg_embeds is None:
                raise ValueError(
                    "SANA-WM streaming CFG requires negative prompt embeds."
                )
            pos_embeds, neg_embeds, pos_mask, neg_mask = (
                _align_sana_wm_cfg_text_conditions(
                    pos_embeds, neg_embeds, pos_mask, neg_mask
                )
            )
        embeds_in = torch.cat([neg_embeds, pos_embeds], dim=0) if do_cfg else pos_embeds
        mask_in = _cat_optional_tensors(neg_mask, pos_mask) if do_cfg else pos_mask
        if _SANAWM_INJECT_DIR and iload is not None and not do_cfg:
            _cond = iload("cond").to(device=device, dtype=target_dtype)
            while _cond.dim() > embeds_in.dim():
                _cond = _cond.squeeze(1)
            embeds_in = _cond
            mask_in = iload("cond_mask").to(device=device)

        # --- camera / plücker (FULL length; forward_long windows internally) ---
        extra = batch.extra or {}

View on GitHub (pinned to 0132848349)

Solutions

  1. Provide a negative prompt (or ensure an empty-string default is encoded) when streaming CFG is enabled
  2. Add the negative-prompt encoding stage to the pipeline for CFG runs
  3. Or set streaming_cfg_scale = 1.0 to disable CFG entirely

Example fix

# before
req.negative_prompt = None  # neg embeds never produced
# after
req.negative_prompt = req.negative_prompt or ""
batch = neg_text_encode_stage.forward(batch, server_args)
Defensive patterns

Strategy: validation

Validate before calling

if do_cfg:
    assert pcfg.get_neg_prompt_embeds(batch) is not None, "encode a negative prompt (or empty string) when streaming CFG is on"

Type guard

def cfg_ready(pcfg, batch) -> bool:
    return pcfg.get_neg_prompt_embeds(batch) is not None or not do_classifier_free_guidance(batch)

Try / catch

try:
    resp = stage.forward(batch, server_args)
except ValueError as e:
    if "negative prompt embeds" in str(e):
        sampler.streaming_cfg_scale = 1.0  # degrade to no-CFG
        resp = stage.forward(batch, server_args)
    else:
        raise

Prevention

When it happens

Trigger: Setting streaming_cfg_scale > 1.0 with do_classifier_free_guidance but the request/pipeline never produced negative prompt embeds (no negative prompt given and no default encoded).

Common situations: Clients request CFG without a negative prompt; the negative-encoding stage skipped because the field was empty rather than encoding an empty-string negative; partial pipeline wiring for the CFG branch.

Related errors


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