{"record":{"id":"8d1d2fa6df3880bd","repo":"tracel-ai/burn","slug":"can-t-differentiate-avg-pool-2d-backward","errorCode":null,"errorMessage":"Can't differentiate avg pool 2d backward.","messagePattern":"Can't differentiate avg pool 2d backward\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-autodiff/src/ops/module.rs","lineNumber":1498,"sourceCode":"                kernel_size,\n                stride,\n                padding,\n                count_include_pad,\n                ceil_mode,\n            )),\n        }\n    }\n\n    fn avg_pool2d_backward(\n        _x: AutodiffTensor<B>,\n        _grad: AutodiffTensor<B>,\n        _kernel_size: [usize; 2],\n        _stride: [usize; 2],\n        _padding: [usize; 2],\n        _count_include_pad: bool,\n        _ceil_mode: bool,\n    ) -> AutodiffTensor<B> {\n        panic!(\"Can't differentiate avg pool 2d backward.\");\n    }\n\n    fn max_pool1d(\n        x: AutodiffTensor<B>,\n        kernel_size: usize,\n        stride: usize,\n        padding: usize,\n        dilation: usize,\n        ceil_mode: bool,\n    ) -> AutodiffTensor<B> {\n        match MaxPool1D\n            .prepare::<C>([x.node.clone()])\n            .compute_bound()\n            .stateful()\n        {\n            OpsKind::Tracked(mut prep) => {\n                let x_state = prep.checkpoint(&x);\n                let settings = get_device_settings::<B>(&x.primitive.device());","sourceCodeStart":1480,"sourceCodeEnd":1516,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-autodiff/src/ops/module.rs#L1480-L1516","documentation":"The autodiff backend does not implement the backward pass of avg_pool2d. Its module ops module implements only the forward pass; calling the backward entry point hits an unconditional panic because no gradient rule exists for this op on this backend combination.","triggerScenarios":"Calling burn_autodiff::module::avg_pool2d_backward directly, or a code path (e.g. a custom op or delegated backward) that requests the gradient of an avg_pool2d output from AutodiffTensor<B> where the inner backend does not provide it.","commonSituations":"Training a CNN with AvgPool2d layers on an autodiff-wrapped backend that lacks its own pool backward; upgrading burn to a version where the inner backend's pool backward is not yet implemented; hand-rolling backward passes against the module ops API.","solutions":["Use max_pool2d instead of avg_pool2d for pooling in layers that need gradients on this backend","Enable/upgrade the inner backend (e.g. burn-tch or burn-candle) so it supplies its own avg_pool2d backward","Downsample via strided conv2d or reshape+mean reduction composed of ops the autodiff backend supports","Implement avg_pool2d_backward for your backend by delegating to its primitives"],"exampleFix":"// before\nlet pooled = pool::avg_pool2d(&x, [2, 2], [2, 2], [0, 0], true, false);\n// after\nlet pooled = pool::max_pool2d(&x, [2, 2], [2, 2], [0, 0], false);","handlingStrategy":"fallback","validationCode":"// Before training, verify pooling layers use ops with backward support on autodiff\nif uses_avg_pool2d(&model_config) {\n    eprintln!(\"avg_pool2d backward is unimplemented in burn-autodiff; use max_pool2d or strided conv\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer max_pool2d or strided conv2d for trainable pooling on autodiff","Check the backend's module ops for a *_backward implementation before using a forward op in training","Run a single training step as a smoke test before long runs to surface stub panics early"],"tags":["rust","autodiff","unimplemented","backward-pass"],"backgroundTag":"unimplemented-op-backward","analyzedSha":"d16f7ba2ed0d41408189384044cc886fb4c8f957","analyzedAt":"2026-09-05T13:19:14.260Z","contentChangedAt":"2026-09-05T13:19:14.260Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}