JuliaDiff / JuliaDiff/DifferentiationInterface.jl

Bug(Zygote): derivative fails when Zygote returns nothing gradient

Open Beginner friendly
#1,011 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bot
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.