diff --git a/src/diffusers/schedulers/scheduling_flow_match_euler_discrete.py b/src/diffusers/schedulers/scheduling_flow_match_euler_discrete.py index 0e4f5c6a1f97..cdfef1bcbd2e 100644 --- a/src/diffusers/schedulers/scheduling_flow_match_euler_discrete.py +++ b/src/diffusers/schedulers/scheduling_flow_match_euler_discrete.py @@ -128,6 +128,13 @@ def __init__( timesteps = torch.from_numpy(timesteps).to(dtype=torch.float32) sigmas = timesteps / num_train_timesteps + # Store sigma_min / sigma_max from the *unshifted* sigmas. `set_timesteps` uses these + # to seed the per-call schedule and then re-applies `shift` itself — storing the + # post-shift values here would make `set_timesteps` shift a second time and produce + # sigmas that don't match `__init__`'s schedule (#13243). + self.sigma_min = sigmas[-1].item() + self.sigma_max = sigmas[0].item() + if not use_dynamic_shifting: # when use_dynamic_shifting is True, we apply the timestep shifting on the fly based on the image resolution sigmas = shift * sigmas / (1 + (shift - 1) * sigmas) @@ -140,8 +147,6 @@ def __init__( self._shift = shift self.sigmas = sigmas.to("cpu") # to avoid too much CPU/GPU communication - self.sigma_min = self.sigmas[-1].item() - self.sigma_max = self.sigmas[0].item() @property def shift(self):