huggingface/candle · error · candle::Error

one_hot: index value {value} exceeds depth {depth}

Error message

one_hot: index value {value} exceeds depth {depth}

What it means

candle-nn's one_hot helper writes a marker value into a flat vector at `offset + value`. Before writing, it validates that the class index is non-negative and strictly less than `depth` (the number of one-hot slots per entry). This bail fires when the supplied class index is >= depth, i.e. the index does not fit in the requested one-hot width.

Source

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

    value: I,
    offset: usize,
    depth: usize,
    v: &mut [D],
    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. Increase the `depth` argument of one_hot to be strictly greater than every index in the tensor (e.g. depth = num_classes including any padding label).
  2. Filter or remap out-of-range labels (padding/ignore values like 255 or -1-for-background) before calling one_hot.
  3. Verify label max: compute labels.max_all()? (or min/max on CPU) and assert it is < depth before encoding.
  4. Check for 1-indexed labels from an external dataset; convert to 0-indexed by subtracting 1 if appropriate.

Example fix

// before: labels contain class 255 (padding), depth = num_classes
let onehot = one_hot(&labels, num_classes)?; // panics/errors for 255
// after: clamp/filter padding labels first
let valid = labels.lt(num_classes as u32)?;
let labels = labels.masked_fill(&valid logical_not, 0u32)?;
let onehot = one_hot(&labels, num_classes)?;
Defensive patterns

Strategy: validation

Validate before calling

let max_idx = labels.min_max()?.1.to_scalar::<u32>()?;
if max_idx as usize >= depth {
    return Err(anyhow!("label index {max_idx} exceeds one_hot depth {depth}"));
}

Type guard

fn indices_fit(labels: &Tensor, depth: usize) -> candle::Result<bool> {
    Ok(labels.min_max()?.1.to_scalar::<u32>()? as usize < depth)
}

Try / catch

match one_hot(&labels, depth) {
    Ok(t) => t,
    Err(e) if e.to_string().contains("exceeds depth") => {
        // remap padding labels and retry
        one_hot(&labels.clamp(0u32, (depth as u32) - 1)?, depth)?
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling candle_nn::encoding::one_hot with an index tensor containing a value equal to or greater than the `depth` argument (e.g. one_hot(labels, depth=10) where a label is 10 or 255). The check is `value >= depth` after the value is cast to usize.

Common situations: Num-class mismatch: labels tensor created for a 1000-class dataset but model/one-hot built with depth=100; padding label values (e.g. 255 mask) accidentally included in the label tensor; off-by-one where classes are 1-indexed so max label == depth; vocab-size shrink after model version change.

Related errors


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