huggingface/candle · error · candle::Error

one_hot: index out of bounds {idx}, len {}

Error message

one_hot: index out of bounds {idx}, len {}

What it means

After the depth check passes, set_at_index computes `idx = offset + value` into the flat output vector of length batch*depth (plus any offset base). If the computed flat position still falls outside the vector, this bail fires — it indicates the `offset` argument is inconsistent with the vector length rather than a bad class value.

Source

Thrown at candle-nn/src/encoding.rs:146

    on_value: D,
) -> Result<()> {
    let value = value.into();
    // Skip for an entire row of off_values
    if value == -1 {
        return Ok(());
    }
    if value < -1 {
        bail!(
            "one_hot: invalid negative index value {value}, expected a positive index value or -1"
        );
    }
    let value = value as usize;
    if value >= depth {
        bail!("one_hot: index value {value} exceeds depth {depth}")
    }
    let idx = offset + value;
    if idx >= v.len() {
        bail!("one_hot: index out of bounds {idx}, len {}", v.len());
    }
    v[idx] = on_value;
    Ok(())
}

View on GitHub (pinned to d5fee525bf)

Solutions

  1. Ensure the destination vector length equals batch_size * depth and each offset is batch_index * depth before calling set_at_index.
  2. Re-allocate the one-hot buffer from the actual tensor batch size instead of reusing a cached buffer.
  3. Update/upgrade candle-nn — if this fires from the public one_hot API itself, it is a sizing bug; check for a fixed release or file an issue with the reproducing shapes.
  4. As a workaround, build the one-hot tensor manually via zeros + scatter_add or Tensor::onehot-equivalent ops.

Example fix

// before: buffer allocated for old batch
let mut v = vec![off_value; old_bsz * depth];
// after
let bsz = labels.elem_count();
let mut v = vec![off_value; bsz * depth];
for (i, &val) in labels.to_vec1::<u32>()?.iter().enumerate() {
    set_at_index(&mut v, i * depth, val as usize, depth, on_value)?;
}
Defensive patterns

Strategy: validation

Validate before calling

let bsz = labels.elem_count();
assert_eq!(buffer.len(), bsz * depth, "one_hot buffer sized {} != {}", buffer.len(), bsz * depth);

Try / catch

let result = std::panic::catch_unwind(|| one_hot(&labels, depth));
match result {
    Ok(Ok(t)) => t,
    _ => {
        let v = vec![0f32; labels.elem_count() * depth]; // re-allocate correctly sized buffer
        one_hot(&labels, depth)?
    }
}

Prevention

When it happens

Trigger: Calling one_hot where the internal buffer v does not have room for offset+value: i.e. v.len() <= offset + value. Practically this arises when the output buffer was allocated for a smaller depth/batch than the offsets/indexes assume.

Common situations: Library-internal buffer sizing bug or a custom call to set_at_index with mismatched offset and buffer length; batch-size mismatch between the allocated one-hot buffer and the number of labels; partially filled/stale buffer reused across calls.

Related errors


AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02). Data as JSON: /api/errors/73b1d521468ea6eb. Report an issue: GitHub.