invoke-ai/InvokeAI · error · ValueError

Negative conditioning is required when cfg_scale != 1.0

Error message

Negative conditioning is required when cfg_scale != 1.0

What it means

In the Heun denoise path, classifier-free guidance needs both conditional and negative (unconditional) predictions whenever cfg_scale != 1.0 for a given step. If negative text embeddings (neg_text_bth/neg_text_lens) were not supplied, the library raises ValueError because it cannot compute the guided prediction.

Source

Thrown at invokeai/backend/ernie_image/denoise.py:122

            img = _blend_init_latents(init_latents, img, float(scheduler.sigmas[0]))

        # Higher-order solvers evaluate the model more than once per requested step (Heun's
        # `set_timesteps(N)` yields 2N-1 timesteps), so drive progress off the actual iteration
        # count rather than the requested step count.
        total_steps = len(scheduler.timesteps)

        pbar = tqdm(total=total_steps, desc="ERNIE-Image denoising")
        for step_index in range(total_steps):
            timestep = scheduler.timesteps[step_index]
            # The scheduler's timestep is already in `[0, num_train_timesteps]`; pass directly.
            t_model = timestep.item()
            t_vec = torch.full((img.shape[0],), t_model, dtype=img.dtype, device=img.device)

            pred = _forward(model, img, t_vec, text_bth, text_lens)
            step_cfg = cfg_scale[min(step_index, len(cfg_scale) - 1)]
            if not math.isclose(step_cfg, 1.0):
                if neg_text_bth is None or neg_text_lens is None:
                    raise ValueError("Negative conditioning is required when cfg_scale != 1.0")
                neg_pred = _forward(model, img, t_vec, neg_text_bth, neg_text_lens)
                pred = neg_pred + step_cfg * (pred - neg_pred)

            # `generator` matters for stochastic schedulers (LCM re-noises every step). Euler and
            # Heun accept it too and only consult it when `s_churn > 0`, which is 0 on this path.
            img = scheduler.step(model_output=pred, timestep=timestep, sample=img, generator=generator).prev_sample

            t_prev = scheduler.sigmas[step_index + 1].item() if step_index + 1 < len(scheduler.sigmas) else 0.0
            if inpaint_extension is not None:
                img = inpaint_extension.merge_intermediate_latents_with_init_latents(img, t_prev)

            pbar.update(1)
            # Predicted x0 estimate, unpatched so the preview decoder can use standard
            # 32-channel latent RGB factors. `img` has already been stepped to `t_prev`, so the
            # x0 estimate must use `t_prev` (using the pre-step sigma would over-subtract).
            preview = unpatchify_latents(img - t_prev * pred)
            step_callback(
                PipelineIntermediateState(

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Provide negative conditioning tensors (encode the negative prompt and pass neg_text_bth/neg_text_lens).
  2. Set cfg_scale to 1.0 if you don't want classifier-free guidance and have no negative prompt.
  3. Encode an empty-string negative prompt as a default in your graph.

Example fix

// before
denoise(model, cfg_scale=3.0, neg_text_bth=None)
// after
neg_bth, neg_lens = encode_text(model, "")
denoise(model, cfg_scale=3.0, neg_text_bth=neg_bth, neg_text_lens=neg_lens)
Defensive patterns

Strategy: validation

Validate before calling

if any(c != 1.0 for c in cfg_scale) and (neg_text_bth is None or neg_text_lens is None):
    raise ValueError("encode a negative prompt before enabling CFG")

Type guard

def has_negative_conditioning(neg_bth, neg_lens) -> bool:
    return neg_bth is not None and neg_lens is not None

Try / catch

try:
    img = denoise(model, cfg_scale=cfg, neg_text_bth=neg_bth, neg_text_lens=neg_lens)
except ValueError as e:
    if "Negative conditioning" in str(e):
        neg_bth, neg_lens = encode_text(model, "")
        img = denoise(model, cfg_scale=cfg, neg_text_bth=neg_bth, neg_text_lens=neg_lens)
    else:
        raise

Prevention

When it happens

Trigger: Calling denoise() with a cfg_scale (any per-step entry) != 1.0 while passing neg_text_bth=None or neg_text_lens=None through the Heun branch.

Common situations: Graphs omitting the negative prompt node while setting CFG > 1; pipelines migrated from CFG-free workflows where cfg_scale was previously 1.0.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/1814a45c86cd9fd7. Report an issue: GitHub.