tracel-ai/burn · info
grid_sample_2d: NumCast::from({x:?}) to {:?} returned None
Error message
grid_sample_2d: NumCast::from({x:?}) to {:?} returned None What it means
Inside grid_sample_2d_impl, from_f64 converts computed coordinates back to the element type T via NumCast::from, which returns None when the f64 value is not representable in T. The panic is a diagnostic hatch: for current float dtypes ToElement::to_f64 preserves non-finite values so from() always succeeds; if a future dtype breaks that invariant, this panic surfaces it.
Source
Thrown at crates/burn-flex/src/ops/grid_sample.rs:105
let g_stride_h = w_out * 2;
let o_stride_n = channels * h_out * w_out;
let o_stride_c = h_out * w_out;
let o_stride_h = w_out;
// Low-precision types (f16/bf16) are widened to f64 for all arithmetic so
// that coordinate math, weights, and accumulated samples keep full precision.
//
// The from_f64 unwrap is unreachable for any well-formed input: bilinear
// is a convex combination of finite samples so the result stays bounded by
// the sample envelope. The `half` crate's `NumCast` impl for f16/bf16
// forwards through `to_f32` and maps non-finite inputs to `Some(inf/nan)`;
// `num_traits`'s f32/f64 impls do the same. The message-bearing panic is a
// diagnostic hatch for future dtypes where this invariant does not hold.
let to_f64 = |x: T| -> f64 { ToElement::to_f64(&x) };
let from_f64 = |x: f64| -> T {
<T as NumCast>::from(x).unwrap_or_else(|| {
panic!(
"grid_sample_2d: NumCast::from({x:?}) to {:?} returned None",
T::dtype()
)
})
};
for b in 0..batch_size {
for y in 0..h_out {
for x in 0..w_out {
let g_idx = b * g_stride_n + y * g_stride_h + x * 2;
let sample_x = to_f64(grid_data[g_idx]);
let sample_y = to_f64(grid_data[g_idx + 1]);
let (px, py) = if align {
let px = (sample_x + 1.0) * ((w_in - 1) as f64) / 2.0;
let py = (sample_y + 1.0) * ((h_in - 1) as f64) / 2.0;
(px, py)
} else {View on GitHub (pinned to d16f7ba2ed)
Solutions
- Nothing to fix for stock float dtypes — this path cannot return None there
- If you hit it with a custom dtype, ensure its NumCast impl and to_f64 conversion are lossless for non-finite values
- Clamp grid coordinates to finite values before grid_sample when feeding unusual data
- Report it to burn-flex maintainers with the dtype and input values if reachable
Defensive patterns
Strategy: try-catch
Validate before calling
// ensure grid coordinates are finite before grid_sample_2d assert!(grid.to_data().value.iter().all(|v| v.is_finite() || v.is_nan()), "non-finite handling differs per dtype");
Try / catch
// this panic is not catchable in Rust without catch_unwind
let result = std::panic::catch_unwind(AssertUnwindSafe(||
backend.grid_sample_2d(tensor.clone(), grid.clone(), options.clone())
)); Prevention
- Stick to stock float dtypes (F32/F64/F16/BF16) for grid_sample
- Keep grid coordinates finite; sanitize inputs if upstream may emit inf
When it happens
Trigger: Effectively unreachable with F32/F64/F16/BF16 today; would trigger if a non-standard element type T were used where to_f64 loses representability (e.g. an integer T given a fractional/overflowing f64 coordinate).
Common situations: Custom element types added to the backend, or extreme NaN/inf handling differences in a future dtype; as a library user on stock float dtypes you should not hit this.
Related errors
- grid_sample_2d: {:?} mode is not supported
- grid_sample_2d: unsupported dtype {:?}
- capture tensor operations must run inside CaptureDevice::cap
- Capture tensors do not support autodiff
- Autodiff should not wrap an autodiff tensor.
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/94bbf3d15d2875b6.
Report an issue: GitHub.