Overview
@rhayes777 filed five issues on 2026-05-23 while auditing released 2026.5.21.1
against the documented public API: PyAutoArray#332, PyAutoArray#333,
PyAutoGalaxy#440, PyAutoLens#531, PyAutoLens#532. They received zero replies for
66 days. All five were answered on 2026-07-28, and every one of the 16 findings
was re-verified against current main first — all 16 still reproduce.
This epic tracks the campaign that fixes them. It exists because all five replies
promise @rhayes777 a single place to watch.
Decision (2026-07-28): we implement in-house. His "Happy to PR if useful" offer
was declined warmly — the affected constructors sit on JAX-traced hot paths and
guards that stay correct under tracing are not a fair hand-off.
Verified against main
PyAutoArray@616e8b4c · PyAutoGalaxy@f0b65f39 · PyAutoLens@6567b3b1c — all clean,
zero ahead/behind.
| Issue |
Findings |
Verified |
| #332 |
ConstantSplit×RectangularUniform; adaptive-mesh precondition error |
3/3 |
| #333 |
B5, B6, B7, B8, B13 — input validation |
5/5 |
| PyAutoGalaxy#440 |
B9, B10, B11, B12 — profile validation |
4/4 |
| PyAutoLens#531 |
PointSolver AxisError + IndexError |
2/2 |
| PyAutoLens#532 |
B4 + redshift ordering |
2/2 |
Correction to #332's headline
#332 reports that Delaunay and KNNBarycentric are "unusable in FitImaging".
They are not. They require an image-plane mesh grid via adapt_images, and with
it both fit cleanly:
Delaunay(pixels=100) + Constant + adapt_images -> log_evidence 5084.7513
KNNBarycentric(pixels=100) + Constant + adapt_images -> log_evidence 5211.7226
Delaunay(pixels=100) + Constant, NO adapt -> AttributeError 'NoneType'
RectangularUniform(15,15) + ConstantSplit -> AttributeError (Split unsupported)
RectangularAdaptDensity + ConstantSplit -> IndexError (Split unsupported)
Delaunay(pixels=100) + ConstantSplit + adapt -> log_evidence 5096.4420
The real defect is that a missing precondition surfaces as
AttributeError: 'NoneType' object has no attribute 'array' from inside
border_relocator.py, naming nothing the caller controls.
This inverts the fix direction. A regression test must assert that bare
construction fails clearly, naming adapt_images — not that it succeeds.
Phases
Phase 1 — genuine crash bugs (real user impact, no workaround) — #416, in progress
Split regularization on rectangular meshes. Rectangular does not support
Split — the fix is a clear "unsupported" exception, not the missing capability.
Verified scope is 9 combinations in 2 failure modes (3 rectangular meshes x 3
Split regularizations): RectangularUniform → AttributeError (property absent);
RectangularAdaptDensity / RectangularAdaptImage → IndexError (the pass-through
at rectangular.py:460 claims split "reuses the same mappings", which crashes one
frame later in reg_split_from). Delaunay + ConstantSplit works, so this is
specific to the rectangular family.
PointSolver.solve on a source outside the caustic → numpy AxisError
PointSolver.solve with loose pixel_scale_precision → IndexError
(same source at 0.001 returns 4 images)
Phase 2 — constructor validation sweep (9 findings: B4–B13)
One shared _validate_* helper. Where it lives must be decided before writing
it — PyAutoArray is the natural floor, since Galaxy and Lens both depend on it —
or the three repos ship inconsistent messages.
Phase 3 — error legibility
adapt_images precondition fails fast and legibly; regression test asserts the
clear failure. Plus B10 (2.357e-06 Isothermal/IsothermalSph difference at the
degenerate point) pinned at an explicit tolerance — not chased to bit-identity.
Phase 4 — HELD, awaiting @rhayes777
z_lens > z_source should warn rather than raise (multi-plane genuinely supports
geometries that look wrong under two-plane naming); negative redshift can raise
outright. The #532 reply asks him whether even a warning would be noise in a real
multi-plane setup. Held until he answers — everything else is unblocked.
Constraint carried into every phase
These constructors are JAX-traced. Guards must stay correct under tracing and
cost nothing when traced — no Python if on values that may be tracers.
Sharpened finding on B13
constant.py:43 squares the coefficient, which is why log_evidence is identical
for +1.0 and -1.0. But regularization_weights_from (constant.py:127) returns
the raw un-squared value, so a negative coefficient does leak negative
regularization weights into every consumer of that method. Not inert.
Overview
@rhayes777 filed five issues on 2026-05-23 while auditing released
2026.5.21.1against the documented public API: PyAutoArray#332, PyAutoArray#333,
PyAutoGalaxy#440, PyAutoLens#531, PyAutoLens#532. They received zero replies for
66 days. All five were answered on 2026-07-28, and every one of the 16 findings
was re-verified against current
mainfirst — all 16 still reproduce.This epic tracks the campaign that fixes them. It exists because all five replies
promise @rhayes777 a single place to watch.
Decision (2026-07-28): we implement in-house. His "Happy to PR if useful" offer
was declined warmly — the affected constructors sit on JAX-traced hot paths and
guards that stay correct under tracing are not a fair hand-off.
Verified against main
PyAutoArray@616e8b4c · PyAutoGalaxy@f0b65f39 · PyAutoLens@6567b3b1c — all clean,
zero ahead/behind.
ConstantSplit×RectangularUniform; adaptive-mesh precondition errorAxisError+IndexErrorCorrection to #332's headline
#332 reports that
DelaunayandKNNBarycentricare "unusable inFitImaging".They are not. They require an image-plane mesh grid via
adapt_images, and withit both fit cleanly:
The real defect is that a missing precondition surfaces as
AttributeError: 'NoneType' object has no attribute 'array'from insideborder_relocator.py, naming nothing the caller controls.This inverts the fix direction. A regression test must assert that bare
construction fails clearly, naming
adapt_images— not that it succeeds.Phases
Phase 1 — genuine crash bugs (real user impact, no workaround) — #416, in progress
Splitregularization on rectangular meshes. Rectangular does not supportSplit— the fix is a clear "unsupported" exception, not the missing capability.Verified scope is 9 combinations in 2 failure modes (3 rectangular meshes x 3
Splitregularizations):RectangularUniform→AttributeError(property absent);RectangularAdaptDensity/RectangularAdaptImage→IndexError(the pass-throughat
rectangular.py:460claims split "reuses the same mappings", which crashes oneframe later in
reg_split_from).Delaunay+ConstantSplitworks, so this isspecific to the rectangular family.
PointSolver.solveon a source outside the caustic →numpy AxisErrorPointSolver.solvewith loosepixel_scale_precision→IndexError(same source at 0.001 returns 4 images)
Phase 2 — constructor validation sweep (9 findings: B4–B13)
One shared
_validate_*helper. Where it lives must be decided before writingit — PyAutoArray is the natural floor, since Galaxy and Lens both depend on it —
or the three repos ship inconsistent messages.
Phase 3 — error legibility
adapt_imagesprecondition fails fast and legibly; regression test asserts theclear failure. Plus B10 (
2.357e-06Isothermal/IsothermalSph difference at thedegenerate point) pinned at an explicit tolerance — not chased to bit-identity.
Phase 4 — HELD, awaiting @rhayes777
z_lens > z_sourceshould warn rather than raise (multi-plane genuinely supportsgeometries that look wrong under two-plane naming); negative redshift can raise
outright. The #532 reply asks him whether even a warning would be noise in a real
multi-plane setup. Held until he answers — everything else is unblocked.
Constraint carried into every phase
These constructors are JAX-traced. Guards must stay correct under tracing and
cost nothing when traced — no Python
ifon values that may be tracers.Sharpened finding on B13
constant.py:43squares the coefficient, which is whylog_evidenceis identicalfor
+1.0and-1.0. Butregularization_weights_from(constant.py:127) returnsthe raw un-squared value, so a negative coefficient does leak negative
regularization weights into every consumer of that method. Not inert.