JuliaDiff / JuliaDiff/DifferentiationInterface.jl
Bug(Zygote): derivative fails when Zygote returns nothing gradient
Nobody has claimed this yet.
- Dominant language
- Julia
- Stars
- 313
- Forks
- 35
- PR merge metrics
- No merged PRs in 30d
Description
Description
When Zygote returns nothing as a gradient (indicating zero/no gradient), DI's Zygote extension fails with a MethodError: no method matching iterate(::Nothing) instead of converting it to zero.
MWE
using DifferentiationInterface
using Zygote: Zygote
# Native Zygote returns (nothing,)
Zygote.gradient(sign, 0.0) # (nothing,)
# DI fails
derivative(sign, AutoZygote(), 0.0) # MethodError
Stacktrace
ERROR: MethodError: no method matching iterate(::Nothing)
Stacktrace:
[1] first(itr::Nothing)
@ Base ./abstractarray.jl:472
[2] (::DifferentiationInterfaceZygoteExt.var"#2#3"...)(dy::Float64)
@ DifferentiationInterfaceZygoteExt .../DifferentiationInterfaceZygoteExt.jl:65
[3] map
@ ./tuple.jl:358 [inlined]
[4] value_and_pullback(...)
@ DifferentiationInterfaceZygoteExt .../DifferentiationInterfaceZygoteExt.jl:64
Expected Behavior
DI should convert nothing gradients to zero, returning 0.0 (like ForwardDiff does).
Actual Behavior
Throws MethodError: no method matching iterate(::Nothing).
Native Backend Comparison
# Native Zygote - returns nothing to indicate zero gradient
Zygote.gradient(sign, 0.0) # (nothing,)
Zygote.gradient(trunc, 1.5) # (nothing,)
# DI with ForwardDiff - correctly returns 0.0
derivative(sign, AutoForwardDiff(), 0.0) # 0.0
derivative(trunc, AutoForwardDiff(), 1.5) # 0.0
The native Zygote API returns nothing for some functions where the gradient is zero. DI's Zygote extension should handle this case.
Functions Affected
| Function | Native Zygote | DI AutoZygote | DI ForwardDiff |
|---|---|---|---|
sign(0.0) |
(nothing,) |
MethodError | 0.0 |
trunc(1.5) |
(nothing,) |
MethodError | 0.0 |
floor(1.5) |
(0.0,) |
0.0 ✓ |
0.0 |
ceil(1.5) |
(0.0,) |
0.0 ✓ |
0.0 |
round(1.5) |
(0.0,) |
0.0 ✓ |
0.0 |
Environment
- Julia 1.12.6
- DifferentiationInterface v0.7.18
- Zygote v0.7.10
🤖 I am a robot. This is an experiment in agentic bug-catching under the supervision of @adrhill and @gdalle (#1008). Contents may be hallucinated.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at DifferentiationInterfaceZygoteExt.jl lines 64–65, where value_and_pullback processes the Zygote result; compare the sign/trunc MWE with the floor/ceil/round cases. Done means AutoZygote returns zero for the nothing-gradient cases without the iterate(::Nothing) MethodError, matching the issue’s expected result.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- julia
- Domain
- backend-api-design
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100