Overview
Release re-validation (run 29341418859, wheels 2026.7.14.1.dev65901) reported two chained-pipeline FAILs — interferometer/.../multi_gaussian_expansion/slam.py (numpy.linalg.LinAlgError: Singular matrix) and imaging/features/pixelization/cpu_fast_modeling.py (autoarray.exc.InversionException). Investigation + reproduction (dev venv, jax 0.10.2, matches release) shows this is a flaky test-mode tail, not a deterministic library bug: real inference is already protected by the resample guard in log_likelihood_function; the crash fires only in PYAUTO_TEST_MODE chained runs where an under-converged/fabricated model reaches an unguarded downstream inversion, and only tips into a raised exception under specific numeric conditions. Fix is therefore test-mode-gated in PyAutoArray and must not perturb real-mode numerics.
Plan
- In normal mode, inversion behaviour is byte-for-byte unchanged (still raises → still resamples in the guarded likelihood).
- Only when
is_test_mode() (from autoconf), the inversion sites return a benign dummy instead of raising — neutralising the singular case wherever the inversion is invoked (likelihood, preload, result, chaining), which is why per-path guards in PyAutoLens are unnecessary.
- No conditioning floor / jitter: that would shift every real evidence/reconstruction and conflicts with the "no silent guards / fix the producer" rule.
- Validate with a numpy-only unit test; do not use the flaky end-to-end scripts as a gate.
Detailed implementation plan
Affected Repositories
Branch Survey
| Repository |
Current Branch |
Dirty? |
| ./PyAutoArray |
feature/ticks-minus-in-math |
clean (unrelated; new worktree off origin/main) |
Suggested branch: feature/inversion-testmode-singular-guard
Implementation Steps
autoarray/inversion/inversion/inversion_util.py reconstruction_positive_negative_from (~:224) — wrap xp.linalg.solve in try/except np.linalg.LinAlgError; in test mode return xp.ones_like(data_vector), else raise exc.InversionException.
inversion_util.py reconstruction_positive_only_from (~:344-353) — the except already raises InversionException; in test mode return xp.ones_like(data_vector) instead.
autoarray/inversion/inversion/abstract.py log_det_curvature_reg_matrix_term (~:715-721) — wrap the Cholesky; in test mode return 0.0 on LinAlgError (else the crash moves here once the reconstruction stops raising).
abstract.py log_det_regularization_matrix_term (~:740-746) — same.
- Small shared helper to keep the gate DRY; import
is_test_mode from autoconf.
Key Files
autoarray/inversion/inversion/inversion_util.py — the two reconstruction solvers that raise on singular.
autoarray/inversion/inversion/abstract.py — the two log-det Cholesky evidence terms that also raise on singular.
test_autoarray/inversion/inversion/ — numpy-only unit test for the guard.
Testing
- Numpy-only unit test: a deliberately singular
curvature_reg_matrix (a) raises normally, (b) under monkeypatched PYAUTO_TEST_MODE returns finite dummies.
- No JAX in unit tests; JAX path covered by existing
*_workspace_test parity scripts.
Notes
Follow-up to PyAutoHeart#72 and the G fix PyAutoLens#607. Diagnosis reversed the original prompt's scope (dropped the conditioning floor + PyAutoLens guards). Autonomy: supervised — filed and implemented under --auto; ship sign-off parks for a human.
Overview
Release re-validation (run 29341418859, wheels
2026.7.14.1.dev65901) reported two chained-pipeline FAILs —interferometer/.../multi_gaussian_expansion/slam.py(numpy.linalg.LinAlgError: Singular matrix) andimaging/features/pixelization/cpu_fast_modeling.py(autoarray.exc.InversionException). Investigation + reproduction (dev venv, jax 0.10.2, matches release) shows this is a flaky test-mode tail, not a deterministic library bug: real inference is already protected by the resample guard inlog_likelihood_function; the crash fires only inPYAUTO_TEST_MODEchained runs where an under-converged/fabricated model reaches an unguarded downstream inversion, and only tips into a raised exception under specific numeric conditions. Fix is therefore test-mode-gated in PyAutoArray and must not perturb real-mode numerics.Plan
is_test_mode()(fromautoconf), the inversion sites return a benign dummy instead of raising — neutralising the singular case wherever the inversion is invoked (likelihood, preload, result, chaining), which is why per-path guards in PyAutoLens are unnecessary.Detailed implementation plan
Affected Repositories
Branch Survey
Suggested branch:
feature/inversion-testmode-singular-guardImplementation Steps
autoarray/inversion/inversion/inversion_util.pyreconstruction_positive_negative_from(~:224) — wrapxp.linalg.solveintry/except np.linalg.LinAlgError; in test mode returnxp.ones_like(data_vector), else raiseexc.InversionException.inversion_util.pyreconstruction_positive_only_from(~:344-353) — theexceptalready raisesInversionException; in test mode returnxp.ones_like(data_vector)instead.autoarray/inversion/inversion/abstract.pylog_det_curvature_reg_matrix_term(~:715-721) — wrap the Cholesky; in test mode return0.0onLinAlgError(else the crash moves here once the reconstruction stops raising).abstract.pylog_det_regularization_matrix_term(~:740-746) — same.is_test_modefromautoconf.Key Files
autoarray/inversion/inversion/inversion_util.py— the two reconstruction solvers that raise on singular.autoarray/inversion/inversion/abstract.py— the two log-det Cholesky evidence terms that also raise on singular.test_autoarray/inversion/inversion/— numpy-only unit test for the guard.Testing
curvature_reg_matrix(a) raises normally, (b) under monkeypatchedPYAUTO_TEST_MODEreturns finite dummies.*_workspace_testparity scripts.Notes
Follow-up to PyAutoHeart#72 and the G fix PyAutoLens#607. Diagnosis reversed the original prompt's scope (dropped the conditioning floor + PyAutoLens guards). Autonomy: supervised — filed and implemented under
--auto; ship sign-off parks for a human.