huggingface/candle · error

empty last-dim in arg-sort

Error message

empty last-dim in arg-sort

What it means

arg_sort_last_dim requires a non-empty tensor with a well-defined last dimension; if the tensor has zero dimensions (a rank-0 scalar) there is no last dim to sort along, so it bails. It also requires the tensor to be contiguous. Raised before dispatching the ArgSort op.

Source

Thrown at candle-core/src/sort.rs:275

        n *= 2
    }
    n
}

impl Tensor {
    /// Returns the indices that sort the tensor along the last dimension.
    ///
    /// If `asc` is `true`, sorting is in ascending order. Otherwise sorting is performed in
    /// descending order. The sort is unstable so there is no guarantees on the final order when it
    /// comes to ties.
    pub fn arg_sort_last_dim(&self, asc: bool) -> Result<Tensor> {
        if !self.is_contiguous() {
            return Err(crate::Error::RequiresContiguous {
                op: "arg_sort_last_dim",
            });
        }
        let last_dim = match self.dims().last() {
            None => crate::bail!("empty last-dim in arg-sort"),
            Some(last_dim) => *last_dim,
        };
        // No need for a backward pass for arg sort.
        self.apply_op1_no_bwd(&ArgSort { asc, last_dim })
    }

    /// Sorts the tensor along the last dimension, returns the sorted tensor together with the
    /// sorted indexes.
    ///
    /// If `asc` is `true`, sorting is in ascending order. Otherwise sorting is performed in
    /// descending order. The sort is unstable so there is no guarantees on the final order when it
    /// comes to ties.
    pub fn sort_last_dim(&self, asc: bool) -> Result<(Tensor, Tensor)> {
        if !self.is_contiguous() {
            return Err(crate::Error::RequiresContiguous {
                op: "sort_last_dim",
            });
        }

View on GitHub (pinned to d5fee525bf)

Solutions

  1. Check t.rank() > 0 before sorting; add a batch dimension with t.unsqueeze(0) if needed.
  2. Keep at least the dimension to sort along, e.g. avoid full squeeze/get-to-scalar before topk.
  3. Ensure the tensor is contiguous (call .contiguous() if it came from a transpose/slice).

Example fix

// before
let (v, i) = scores.squeeze(0)?.topk(5)?; // rank-0 -> error
// after
let (v, i) = scores.topk(5)?; // keep rank or unsqueeze
Defensive patterns

Strategy: validation

Validate before calling

if t.rank() == 0 {
    return Err(anyhow!("cannot arg-sort a rank-0 tensor"));
}
if !t.is_contiguous() { let t = t.contiguous()?; }
let (v, i) = t.argsort_last_dim(asc)?;

Try / catch

match t.argsort_last_dim(asc) {
    Ok(s) => s,
    Err(e) if e.to_string().contains("empty last-dim") => t.unsqueeze(0)?.argsort_last_dim(asc)?,
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling argsort/sort/topk on a rank-0 tensor created via Tensor::new(5f32, &dev) or tensor.get(0) on a 1-D tensor, leaving no remaining last dimension. Also triggered indirectly via topk on such a tensor.

Common situations: Indexing/squeezing a tensor down to a scalar in a loop and then trying to topk it; accidentally passing an unbatched scalar result into topk.

Related errors


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