huggingface/candle · error
timestep out of this schedulers bounds: {timestep}
Error message
timestep out of this schedulers bounds: {timestep} What it means
EulerAncestralDiscreteScheduler::scale_model_input looks up the requested timestep in its precomputed timesteps list to find the step_index used to index sigmas. If the timestep is not present in that list, the scheduler cannot compute sigma and bails. The scheduler only accepts exact timesteps it generated at construction time.
Source
Thrown at candle-transformers/src/models/stable_diffusion/euler_ancestral_discrete.rs:162
init_noise_sigma,
config,
})
}
}
impl Scheduler for EulerAncestralDiscreteScheduler {
fn timesteps(&self) -> &[usize] {
self.timesteps.as_slice()
}
/// Ensures interchangeability with schedulers that need to scale the denoising model input
/// depending on the current timestep.
///
/// Scales the denoising model input by `(sigma**2 + 1) ** 0.5` to match the K-LMS algorithm
fn scale_model_input(&self, sample: Tensor, timestep: usize) -> Result<Tensor> {
let step_index = match self.timesteps.iter().position(|&t| t == timestep) {
Some(i) => i,
None => bail!("timestep out of this schedulers bounds: {timestep}"),
};
let sigma = self
.sigmas
.get(step_index)
.expect("step_index out of sigma bounds - this shouldn't happen");
sample / ((sigma.powi(2) + 1.).sqrt())
}
/// Performs a backward step during inference.
fn step(&mut self, model_output: &Tensor, timestep: usize, sample: &Tensor) -> Result<Tensor> {
let step_index = self
.timesteps
.iter()
.position(|&p| p == timestep)
.ok_or_else(|| Error::Msg("timestep out of this schedulers bounds".to_string()))?;
View on GitHub (pinned to d5fee525bf)
Solutions
- Only pass timesteps taken directly from scheduler.timesteps() (or the value yielded by the scheduler's iteration API)
- Re-run set_timesteps(num_inference_steps) and use the resulting list verbatim
- Check for integer truncation when converting float timesteps; match the scheduler's rounding
Example fix
// before
for t in 0..num_steps { scheduler.scale_model_input(x, t)?; }
// after
for &t in scheduler.timesteps().iter() { scheduler.scale_model_input(x, t)?; } Defensive patterns
Strategy: validation
Validate before calling
if !scheduler.timesteps().iter().any(|&t| t == timestep) {
return Err(anyhow::anyhow!("timestep {} not in scheduler timesteps", timestep));
} Try / catch
let out = match scheduler.scale_model_input(sample, t) {
Ok(x) => x,
Err(e) if e.to_string().contains("out of this schedulers bounds") => {
anyhow::bail!("use timesteps from scheduler.timesteps(), got {}", t)
}
Err(e) => return Err(e.into()),
}; Prevention
- Iterate scheduler.timesteps() directly instead of synthesizing timesteps
- Call set_timesteps(num_steps) before the diffusion loop and reuse its output
- Avoid float-to-usize casts that introduce rounding differences
When it happens
Trigger: Calling scale_model_input(sample, timestep) with a timestep value that is not exactly one of the entries in scheduler.timesteps (from set_timesteps/init), including off-by-one, float-rounded, or out-of-range values.
Common situations: Reimplementing a diffusion loop and computing timesteps independently instead of using scheduler.timesteps(); iterating a float sigma schedule and casting to usize differently than the scheduler; reusing a scheduler after re-initializing timesteps with a different step count.
Related errors
- prediction_type not implemented yet: sample
- {} is a dummy type and cannot be constructed
- {} is a dummy type and cannot be converted
- {} is a dummy type and cannot be converted to scalar
- {} is a dummy type and does not support storage
AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02).
Data as JSON: /api/errors/151870eaf45cc149.
Report an issue: GitHub.