{"record":{"id":"8bb9bdea94e27380","repo":"tracel-ai/burn","slug":"autodiff-not-supported-for-custom-op","errorCode":null,"errorMessage":"Autodiff not supported for custom op `{}`","messagePattern":"Autodiff not supported for custom op `(.+?)`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-backend-extension/src/routing.rs","lineNumber":1126,"sourceCode":"        concrete_enabled,\n        autodiff_call,\n        concrete_enabled_output,\n    } = fragments;\n    let dispatch_root = &paths.dispatch_root;\n    let context = quote!(#dispatch_root::DispatchAutodiffContext);\n    let backend_root = &paths.backend_root;\n    let backend_alias = &paths.backend_alias;\n    let strategy = quote!(#dispatch_root::GradientCheckpointingStrategy);\n    let attr = autodiff_attr.cloned().unwrap_or_default();\n    let concrete_enabled_output = if operation.output.contains_float() {\n        concrete_enabled_output\n    } else {\n        concrete_enabled\n    };\n    let concrete_route = if !autodiff {\n        quote! {\n            let #context::Disabled = __ad_ctx else {\n                unimplemented!(\"Autodiff not supported for custom op `{}`\", stringify!(#operation_name))\n            };\n            type #backend_alias = #backend_root::#backend;\n            #concrete_inputs\n            #concrete_invoke\n            #concrete_disabled\n        }\n    } else if autodiff_attr.is_none() {\n        quote! {\n            type #backend_alias = #backend_root::#backend;\n            #concrete_inputs\n            #concrete_invoke\n            match __ad_ctx {\n                #context::Disabled => #concrete_disabled,\n                #context::Enabled(__strategy) => #concrete_enabled_output,\n            }\n        }\n    } else {\n        quote! {","sourceCodeStart":1108,"sourceCodeEnd":1144,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-backend-extension/src/routing.rs#L1108-L1144","documentation":"In burn-backend-extension's generated routing (crates/burn-backend-extension/src/routing.rs:1126), when a custom op was declared without autodiff support (autodiff=false / no autodiff route generated), the autodiff-context route asserts the context is Disabled; if autodiff is actually enabled (__ad_ctx says Enabled), it panics with unimplemented!(\"Autodiff not supported for custom op `{}`\").","triggerScenarios":"Calling a custom op declared without autodiff support while running under burn-autodiff with gradients enabled (Enabled context), e.g. inside a training loop.","commonSituations":"Using a custom op in a model's forward pass during training when the op only declared concrete (non-autodiff) backend routes.","solutions":["Declare autodiff support for the custom op (add the autodiff attribute/route so an autodiff strategy is generated).","Run the op under no_grad / with autodiff disabled (Disabled context).","Use a builtin op with autodiff support for the training path."],"exampleFix":"// before\n#[extension(op)]\n#[backend(...)] // no autodiff route\nfn my_op(x: Tensor) -> Tensor { ... }\n// used in training -> panic\n// after\n#[extension(op)]\n#[backend(...)]\n#[autodiff]\nfn my_op(x: Tensor) -> Tensor { ... }","handlingStrategy":"validation","validationCode":"// only call the custom op outside autodiff if it was not declared with #[autodiff]\nif grad_enabled && !op_declares_autodiff() { panic!(\"op requires autodiff support\"); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Add the autodiff attribute to custom ops used in training paths.","Keep non-differentiable custom ops out of the training forward pass.","Run a one-step training smoke test with every custom op in the graph."],"tags":["rust","burn","custom-op","autodiff","routing"],"backgroundTag":"autodiff-unsupported-for-custom-op","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"}