huggingface/candle · error

backward not supported for upsample_bilinear2d

Error message

backward not supported for upsample_bilinear2d

What it means

candle has no backward implementation for the UpsampleBilinear2D op at all; when backward_step walks the op graph and reaches it, it unconditionally bails. Unlike nearest-neighbor upsampling (whose gradient is a strided sum), bilinear interpolation gradients were simply not implemented.

Source

Thrown at candle-core/src/backprop.rs:412

                    } => {
                        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)?
                    }
                    Op::Gather(arg, indexes, dim) => {
                        let sum_grad = grads.or_insert(arg)?;
                        *sum_grad = sum_grad.scatter_add(indexes, &grad, *dim)?;
                    }
                    Op::Scatter(init, indexes, src, dim) => {
                        let init_sum_grad = grads.or_insert(init)?;
                        *init_sum_grad = init_sum_grad.add(&grad)?;

View on GitHub (pinned to d5fee525bf)

Solutions

  1. Replace upsample_bilinear2d with upsample_nearest2d (backward supported for integer uniform scales).
  2. Replace the bilinear upsample with a ConvTranspose2d layer (learned upsampling), which is differentiable in candle.
  3. Stop the gradient at the upsample by calling detach() on the tensor before the op (training downstream layers only).
  4. Implement the op with primitive ops (e.g. gather + weighted combinations) so autograd can differentiate through it.

Example fix

// before
let up = x.upsample_bilinear2d(64, 64)?;
// after
let up = x.upsample_nearest2d(64, 64)?; // integer, uniform -> backward works
Defensive patterns

Strategy: fallback

Validate before calling

// detect bilinear upsample in graph inputs before building the VarMap training loop
let uses_bilinear = layers.iter().any(|l| l.kind == LayerKind::UpsampleBilinear2D);
if uses_bilinear { eprintln!("warning: bilinear upsample has no backward in candle; swapping to nearest"); }

Try / catch

match loss.backward() { Err(e) if e.to_string().contains("upsample_bilinear2d") => { // rebuild model with upsample_nearest2d or ConvTranspose2d
}, other => other?, }

Prevention

When it happens

Trigger: Any call to Tensor::upsample_bilinear2d(...) (directly or inside a model forward) followed by backward() on a loss that depends on it.

Common situations: Porting PyTorch models using F.interpolate(mode='bilinear') or nn.Upsample(mode='bilinear'); training U-Net-style architectures with bilinear upsampling in candle.

Related errors


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