huggingface/candle · error
backward not supported for non uniform upscaling factors
Error message
backward not supported for non uniform upscaling factors
What it means
Even when both height and width scale factors are integers, candle additionally requires them to be equal (uniform scaling) for the UpsampleNearest2D backward, because the gradient is accumulated with a single square kernel Tensor::ones((c,1,scale_h,scale_w)) fed to conv2d whose stride is set to scale_h. scale_h != scale_w would corrupt that computation, so candle bails.
Source
Thrown at candle-core/src/backprop.rs:403
let kernel = Tensor::ones((c, 1, scale), arg.dtype(), arg.device())?;
let conv_sum = grad.conv1d(&kernel, 0, scale, 1, c)?;
let sum_grad = grads.or_insert(arg)?;
*sum_grad = conv_sum;
}
Op::UpsampleNearest2D {
arg,
target_h,
target_w,
} => {
let (_n, c, h, w) = arg.dims4()?;
if target_h % h != 0 || target_w % w != 0 {
crate::bail!("backward not supported for non integer upscaling factors")
}
let scale_h = target_h / h;
let scale_w = target_w / w;
if scale_h != scale_w {
crate::bail!("backward not supported for non uniform upscaling factors")
};
let kernel =
Tensor::ones((c, 1, scale_h, scale_w), arg.dtype(), arg.device())?;
let conv_sum = grad.conv2d(&kernel, 0, scale_h, 1, c)?;
let sum_grad = grads.or_insert(arg)?;
*sum_grad = conv_sum;
}
Op::UpsampleBilinear2D { .. } => {
crate::bail!("backward not supported for upsample_bilinear2d")
}
Op::SliceScatter0(lhs, rhs, start_rhs) => {
let rhs_sum_grad = grads.or_insert(rhs)?;
let rhs_grad = grad.narrow(0, *start_rhs, rhs.dim(0)?)?;
*rhs_sum_grad = rhs_sum_grad.add(&rhs_grad)?;
let lhs_sum_grad = grads.or_insert(lhs)?;
let lhs_grad = grad.slice_scatter0(&rhs.zeros_like()?, *start_rhs)?;
*lhs_sum_grad = lhs_sum_grad.add(&lhs_grad)?View on GitHub (pinned to d5fee525bf)
Solutions
- Use uniform scale factors so target_h/h == target_w/w (e.g. 2x2, 4x4 upscaling).
- Split the anisotropic upscale into consecutive uniform steps if the scales share a common factor.
- Register a custom backward implementation for anisotropic nearest upsampling.
- Avoid the upsample in autograd contexts: treat it as a fixed preprocessing step outside the graph and drop its gradient.
Example fix
// before let up = x.upsample_nearest2d(8, 12)?; // scale_h=4, scale_w=6 -> non uniform // after let up = x.upsample_nearest2d(8, 8)?; // uniform 4x scaling
Defensive patterns
Strategy: validation
Validate before calling
let (_n, _c, h, w) = x.dims4()?;
if target_h % h != 0 || target_w % w != 0 || (target_h / h) != (target_w / w) {
return Err(anyhow::anyhow!("backward requires uniform integer upscaling: got scale_h={} scale_w={}", target_h / h, target_w / w));
} Try / catch
match result { Err(e) if e.to_string().contains("non uniform upscaling") => { // switch to uniform scale or detach
}, other => other?, } Prevention
- Use a single scale_factor variable instead of separate (scale_h, scale_w) configs.
- Reject anisotropic upsample configs at model-construction time.
- Document that candle nearest-2D backward only supports square integer scales.
When it happens
Trigger: backward() over Op::UpsampleNearest2D where target_h/h != target_w/w, e.g. Tensor::upsample_nearest2d(&t, 8, 12) on input with h=2,w=3 (scale 4 vs 4 is fine, but h=2,w=2 with target 8x12 gives 4 vs 6).
Common situations: Non-square feature maps upsampled with different aspect ratios; models ported from PyTorch that use nn.Upsample(scale_factor=(2.0, 3.0)) or explicit size with anisotropic scaling.
Related errors
- backward not supported for upsample_bilinear2d
- in_channel mismatch between input ({c_in}) and kernel ({c_in
- shape mismatch on {path}: {shape:?} <> {tensor_shape:?}
- in_channel {c_in} is not divisible by the number of groups
- in_channel mismatch between input ({c_in}, groups {groups})
AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02).
Data as JSON: /api/errors/eb30934dfba11ce4.
Report an issue: GitHub.