{"record":{"id":"7c2e44382f50e9b8","repo":"invoke-ai/InvokeAI","slug":"denoising-start-must-be-0-when-no-initial-latents","errorCode":null,"errorMessage":"denoising_start must be 0 when no initial latents are provided. There is nothing to partially denoise, and starting from full-magnitude noise at a reduced sigma tells the model the sample is already partly denoised, which produces garbage.","messagePattern":"denoising_start must be 0 when no initial latents are provided\\. There is nothing to partially denoise, and starting from full-magnitude noise at a reduced sigma tells the model the sample is already partly denoised, which produces garbage\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/app/invocations/ernie_image_denoise.py","lineNumber":196,"sourceCode":"            height=self.height,\n        )\n\n    def _load_init_latents(\n        self,\n        context: InvocationContext,\n        noise: torch.Tensor,\n        device: torch.device,\n        dtype: torch.dtype,\n    ) -> Optional[torch.Tensor]:\n        \"\"\"Load and validate the optional image-to-image starting latents.\n\n        The blend with `noise` deliberately happens in the denoise loop rather than here: only that\n        layer knows the *post-shift* first sigma, since `get_schedule` emits raw schedule values and\n        the scheduler applies its `shift` inside `set_timesteps`.\n        \"\"\"\n        if self.latents is None:\n            if self.denoising_start > 0:\n                raise ValueError(\n                    \"denoising_start must be 0 when no initial latents are provided. There is nothing to \"\n                    \"partially denoise, and starting from full-magnitude noise at a reduced sigma tells the \"\n                    \"model the sample is already partly denoised, which produces garbage.\"\n                )\n            return None\n\n        init_latents = context.tensors.load(self.latents.latents_name).to(device=device, dtype=dtype)\n        if init_latents.shape != noise.shape:\n            raise ValueError(\n                f\"Input latents have shape {tuple(init_latents.shape)} but this graph expects \"\n                f\"{tuple(noise.shape)} (batch, patched channels, height, width). ERNIE-Image latents must be \"\n                \"VAE-encoded, BN-normalized (`sampling_utils.vae_normalize`) and 2x2-patchified \"\n                \"(`sampling_utils.patchify_latents`) before they can be denoised.\"\n            )\n        return init_latents\n\n    def _build_scheduler(self, context: InvocationContext) -> SchedulerMixin:\n        \"\"\"Instantiate the selected scheduler from the pipeline's own `scheduler/` config.","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/invocations/ernie_image_denoise.py#L178-L214","documentation":"_load_init_latents returns None when no initial latents are supplied, meaning generation starts from pure noise. That is only valid at denoising_start == 0; a non-zero start would apply a reduced first sigma to full-magnitude noise, making the model treat fresh noise as a partly denoised sample and yielding corrupted output — so it raises instead.","triggerScenarios":"Creating ErnieImageDenoise with `latents` None (pure txt2img) while `denoising_start` > 0 (e.g. 0.5 for img2img-style partial denoise).","commonSituations":"Reusing an img2img graph after disconnecting the latents input while keeping denoising_start; scripted generation that always sets denoising_start for 'faster' steps; UI presets applying a start value globally.","solutions":["Set denoising_start to 0 when there is no latents input","Or provide initial latents (VAE-encoded image or prior denoise output) to make a non-zero denoising_start meaningful","Review graph templates that hard-code denoising_start without guaranteeing a latents connection"],"exampleFix":"// before\nErnieImageDenoise(latents=None, denoising_start=0.4, ...)\n// after\nErnieImageDenoise(latents=None, denoising_start=0.0, ...)  # or supply latents","handlingStrategy":"validation","validationCode":"if latents is None and denoising_start > 0:\n    raise ValueError(\"denoising_start must be 0 when no initial latents are provided\")","typeGuard":"def denoise_start_is_valid(latents, denoising_start: float) -> bool:\n    return latents is not None or denoising_start == 0","tryCatchPattern":"try:\n    out = invocation.invoke(context)\nexcept ValueError as e:\n    if \"denoising_start must be 0\" in str(e):\n        invocation.denoising_start = 0.0\n        out = invocation.invoke(context)\n    else:\n        raise","preventionTips":["Only set denoising_start > 0 in img2img flows where latents are connected","Reset denoising_start to 0 when removing the latents input from a graph","Audit templates that hard-code denoising_start independently of latents"],"tags":["python","valueerror","denoising","latents","ernie","diffusion"],"backgroundTag":"incompatible-parameter-combination","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}