docs: fix linkcheck and cross-reference CI failures#942
Merged
ChrisRackauckas merged 3 commits intoMay 28, 2026
Conversation
The Documentation workflow on master was failing with three independent errors, all addressed here: 1. **linkcheck** — `https://iopscience.iop.org/article/10.1088/1757-899X/1276/1/012010/` returns a 302 to a PerimeterX bot validator from GitHub Actions runners. Added the URL to the existing `linkcheck_ignore` list in `docs/make.jl`. 2. **cross_references** — `docs/src/solvers/bracketing_solvers.md` referenced `[`modAB`](@ref)` but the exported binding (per commits `e856faf` / `1da0421`) is `ModAB` (uppercase). Fixed the casing. 3. **example_block** — the `@example ill_conditioned_nlprob` block at `docs/src/tutorials/large_systems.md:322-337` tripped `NoFunctionWrapperFoundError` (`No matching function wrapper was found!`) when running `solve(prob_brusselator_2d_approx_di, NewtonRaphson())` against a `NonlinearFunction` whose `sparsity` was `DifferentiationInterface.DenseSparsityDetector(AutoForwardDiff(); atol=1e-4)`. Root cause: `maybe_wrap_nonlinear_f` wraps IIP problem functions with a `FunctionWrappersWrapper` whose signatures are keyed off `ForwardDiff.Dual{Tag{NonlinearSolveTag, Float64}, ...}`. `DenseSparsityDetector{AutoForwardDiff}` runs the wrapped function with ForwardDiff duals whose tag is generated by DI (`Tag{DifferentiationInterface.FixTail{NonlinearFunction{...}}, Float64}`), not `NonlinearSolveTag`. Those duals are *isbits*, so FWW's `AllowNonIsBits` fallback does not kick in, and the dispatch trips `NoFunctionWrapperFoundError`. (Tracer-based detectors happen to work because Tracer types are non-isbits and hit the `AllowNonIsBits` fallback.) Fix: extend the same "skip wrapping in incompatible contexts" pattern introduced by SciML#940 (Enzyme reverse-mode) to the sparsity-detector path. In `maybe_wrap_nonlinear_f`, when `prob.f.sparsity` is a non-`NoSparsityDetector` `AbstractSparsityDetector`, return the raw function unwrapped. The autospecialize gain is also less significant on the sparse path (per-color Jacobian columns are small), so this is the right tradeoff. Test added in `lib/NonlinearSolveBase/test/runtests.jl` asserting that `maybe_wrap_nonlinear_f` wraps under `NoSparsityDetector` (the default) and skips when an `AbstractSparsityDetector` is supplied. Verified locally (Julia 1.12.6): - `Pkg.test("NonlinearSolveBase")`: 40/40 pass (+3 new test cases). - Standalone repro of the docs example_block: both the TracerSparsityDetector and DenseSparsityDetector+AutoForwardDiff variants now `solve` successfully (`retcode = Success`). Without the fix the DenseSparsityDetector variant trips `NoFunctionWrapperFoundError`. - Full docs build with `julia +1.12 --project=docs -e 'include("docs/make.jl")'` (with `linkcheck = false` locally to skip the slow linkcheck pass) runs end-to-end through `Populate: populating indices.` / `RenderDocument: rendering document.` / `HTMLWriter: rendering HTML pages.` with no `Cannot resolve @ref`, no `failed to run @example block`, and no `makedocs encountered errors`. The `linkcheck = false` override is local-only and is not in the committed diff. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
The prior version skipped FunctionWrappers wrapping for *any* `AbstractSparsityDetector` other than `NoSparsityDetector`. This is overbroad: Tracer/Symbolics-style detectors emit non-isbits eltypes (`Tracer`, `Num`, …) which `FunctionWrappersWrappers`' `AllowNonIsBits` fallback already handles correctly — wrapping works for them. Only `DI.DenseSparsityDetector` is the actual failure mode, because it runs the user function with isbits ForwardDiff duals carrying DI's own `FixTail`-tagged Tag, for which no wrapper signature is pre-built and which bypasses `AllowNonIsBits`. Narrow the predicate to `prob.f.sparsity isa DI.DenseSparsityDetector` so Tracer/Symbolics paths keep the AutoSpecialize precompile benefit. The test now exercises three cases: default (wraps), `DenseSparsityDetector` (does not wrap — the regression), and an `AbstractSparsityDetector` proxy for Tracer/Symbolics (wraps). Locally verified that `NLS.solve(prob_brusselator_2d_approx_di, NewtonRaphson())` from docs/src/tutorials/large_systems.md returns `ReturnCode.Success` and that the new testset passes 4/4 on Julia 1.12.6. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Contributor
Author
|
Narrowed Test now exercises three cases (default, |
The FunctionWrappers/ForwardDiff `NoFunctionWrapperFoundError` triggered by `DenseSparsityDetector(AutoForwardDiff())` is a separate, deeper issue that shouldn't be addressed in a docs-CI PR. Restore autospecialize.jl and its test to master; this PR now only carries the linkcheck and cross-reference fixes. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Important
This PR was opened by an agent and should be ignored until reviewed by @ChrisRackauckas.
Summary
Fixes two of the three Documentation-build failures on master.
docs/make.jl— addhttps://iopscience.iop.org/article/10.1088/1757-899X/1276/1/012010/tolinkcheck_ignore. IOP returns a 302 to a PerimeterX bot validator from CI runners, solinkcheckfails.docs/src/solvers/bracketing_solvers.md—[modAB](@ref)→[ModAB](@ref). The exported binding is uppercaseModAB(lib/BracketingNonlinearSolve/src/BracketingNonlinearSolve.jl), so the cross-reference could not resolve.Not included (separate issue)
The third failure — the
@exampleblock indocs/src/tutorials/large_systems.md:322-337trippingNoFunctionWrapperFoundErrorwhenDenseSparsityDetector(AutoForwardDiff())runs the wrapped function with DI'sFixTail-tagged ForwardDiff duals — is a deeper FunctionWrappers/ForwardDiff problem and is out of scope for this docs PR. It is tracked separately. Docs CI will still fail on that example block until it is resolved.Verification (Julia 1.12.6)
Cannot resolve @ref for modAB.linkcheck_ignoreentry matches the exact failing URL from the CI log (linkcheck itself not re-run locally — slow).🤖 Generated with Claude Code