invoke-ai/InvokeAI · error · ValueError

Invalid denoising window: start={denoising_start}, end={deno

Error message

Invalid denoising window: start={denoising_start}, end={denoising_end}

What it means

get_schedule builds a linear sigma schedule (1.0 -> 0.0) sliced to the [denoising_start, denoising_end) window. The window must satisfy 0 <= start < end <= 1; any other combination is ambiguous or empty and raises ValueError.

Source

Thrown at invokeai/backend/ernie_image/sampling_utils.py:65

            torch.zeros((0, 0, text_in_dim), device=device, dtype=dtype),
            torch.zeros((0,), device=device, dtype=torch.long),
        )

    normalized = [
        th.squeeze(1).to(device).to(dtype) if th.dim() == 3 else th.to(device).to(dtype) for th in text_hiddens
    ]
    lens = torch.tensor([t.shape[0] for t in normalized], device=device, dtype=torch.long)
    t_max = int(lens.max().item())
    text_bth = torch.zeros((len(normalized), t_max, text_in_dim), device=device, dtype=dtype)
    for i, t in enumerate(normalized):
        text_bth[i, : t.shape[0], :] = t
    return text_bth, lens


def get_schedule(num_steps: int, denoising_start: float = 0.0, denoising_end: float = 1.0) -> torch.Tensor:
    """Linear sigma schedule from 1.0 -> 0.0, same convention as the upstream pipeline."""
    if not 0.0 <= denoising_start < denoising_end <= 1.0:
        raise ValueError(f"Invalid denoising window: start={denoising_start}, end={denoising_end}")
    sigmas = torch.linspace(1.0, 0.0, num_steps + 1)
    start = int(num_steps * denoising_start)
    end = int(num_steps * denoising_end)
    # Slice to [start, end] inclusive of both ends so the caller can use adjacent pairs.
    window = sigmas[start : end + 1]
    if window.numel() < 2:
        # A window that rounds down to a single sigma yields zero adjacent pairs, i.e. zero steps.
        # The denoise loop would then return its input untouched and the graph would decode raw
        # noise with no error, so refuse instead.
        raise ValueError(
            f"The denoising window [{denoising_start}, {denoising_end}] rounds to zero steps at "
            f"steps={num_steps}. Increase steps or widen the window."
        )
    return window


def vae_normalize(latents: torch.Tensor, bn: torch.nn.Module, eps: float = 1e-5) -> torch.Tensor:
    """Apply the VAE's BatchNorm statistics to map encoder output -> transformer input.

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Ensure denoising_start < denoising_end and both are within [0, 1] before calling.
  2. If a caller passes percentages, divide by 100 first (0-100 -> 0.0-1.0).
  3. Swap/normalize the two values (start = min, end = max) at the graph boundary.

Example fix

// before
get_schedule(20, denoising_start=0.8, denoising_end=0.5)
// after
get_schedule(20, denoising_start=0.5, denoising_end=0.8)
Defensive patterns

Strategy: validation

Validate before calling

assert 0.0 <= denoising_start < denoising_end <= 1.0, f"bad window: {denoising_start}, {denoising_end}"

Type guard

def is_valid_denoise_window(start: float, end: float) -> bool:
    return 0.0 <= start < end <= 1.0

Try / catch

try:
    sigmas = get_schedule(steps, denoising_start=s, denoising_end=e)
except ValueError as e:
    if "Invalid denoising window" in str(e):
        s, e = min(s, e), max(s, e)
        sigmas = get_schedule(steps, denoising_start=s, denoising_end=e)
    else:
        raise

Prevention

When it happens

Trigger: Calling get_schedule with denoising_start >= denoising_end, a negative start, an end > 1.0, or start == end (e.g. get_schedule(20, 0.7, 0.7) or get_schedule(20, 0.5, 0.3)).

Common situations: UI/slider bugs passing unsorted values; graph nodes wired denoising_end into denoising_start; float inputs from percentage fields entered as 0-100 instead of 0-1.

Related errors


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