Overview
The two scripts/guides/results/aggregator/*.py tutorials crash with IndexError: list index out of range under the release-validation profile (surfaced in the 2026-07-13 release tail, PyAutoHeart#72, cluster E). Reproduced on current main — it is not covered by PyAutoFit#1368 (the release profile unsets PYAUTO_TEST_MODE for guides/results/, so is_test_mode() is False and the output-routing fix does not apply).
Root cause: three results tutorials each run their own capped n_like_max=300 Nautilus fit, but only _quick_fit.py disables samples_weight_threshold. The others prune to 2 samples on disk, and the tutorials then deep-index (from_sample_index(-10), parameter_lists[9]) assuming ≥10 samples → IndexError. It is order-dependent: start_here.py runs first and plants the 2-sample fit that the aggregator readers later choke on. The scripts' docstrings already claim they "resume from the cached fit," but their model/search config diverges from _quick_fit, so they don't — they run a separate shallow fit.
Fix: consolidate onto a single fit source (_quick_fit.py). The self-fitting scripts keep their model/search/analysis written out inline (these are teaching docs — no shared "builder" imports), but the inline definition is made to match _quick_fit so search.fit() genuinely resumes its 300-sample fit. Verified: the fit identifier is [search, model, unique_tag] only (analysis-independent), so a matching inline model + plain AnalysisImaging reproduces _quick_fit's on-disk identifier 8bc8f101….
Plan
- Keep
_quick_fit.py as the single fit producer (threshold None, Isothermal + shear, MGE source, AnalysisLatent); make its primary fit unique_tag suffix-free (simple__no_lens_light) plus one more fit for the aggregator's multi-result iteration. (Bonus: fixes queries.py, which queries unique_tag == "simple__no_lens_light" — currently matches nothing.)
start_here.py + galaxies_fits.py: add shear=al.mp.ExternalShear to the lens (they already use the identical MGE source and unique_tag=dataset_name) and match _quick_fit's identifier-affecting search fields, so search.fit() resumes the 300-sample fit. Deep indexing becomes valid.
samples.py: swap the inline Sersic source for the same MGE bulge + shear so it resumes the primary fit; update prose/prints describing the source.
- Correct the now-accurate "resumes from the cached fit" docstrings.
- Leave the read-only aggregator scripts (
samples_via_aggregator, models, queries, data_fitting, interferometer, latent_variables) unchanged — they will only ever read 300-sample fits.
- Regenerate the affected notebooks; validate via the ordered
guides/results release-profile run.
Detailed implementation plan
Affected Repositories
- autolens_workspace (primary)
Branch Survey
| Repository |
Current Branch |
Dirty? |
| ./autolens_workspace |
main |
clean |
Suggested branch: feature/aggregator-quick-fit-consolidation
Implementation Steps
scripts/guides/results/_quick_fit.py — make the primary fit unique_tag=dataset_name (suffix-free) and keep a second distinct fit for aggregator iteration; keep conf.instance["output"]["samples_weight_threshold"] = None, the shear + MGE model, LatentShear/AnalysisLatent. Confirm identifier via the identifier harness.
scripts/guides/results/start_here.py — add shear=al.mp.ExternalShear to the lens af.Model; align the af.Nautilus config with _quick_fit's identifier-affecting fields; fix the docstring (~line 104) that claims resumption. Keep the _quick_fit auto-trigger guard.
scripts/guides/results/aggregator/galaxies_fits.py — same model/search alignment; it still needs dataset for the local al.FitImaging refit. from_sample_index(-10) (lines ~176/238) becomes valid.
scripts/guides/results/aggregator/samples.py — change source al.lp.Sersic → MGE bulge (matching _quick_fit) + add shear; align search; update prose/prints referencing .source.bulge. parameter_lists[9] / log_likelihood_list[9] become valid.
- Regenerate notebooks:
PYTHONPATH=../PyAutoBuild/autobuild python3 ../PyAutoBuild/autobuild/generate.py autolens.
- Validate:
run_python.py autolens scripts/guides/results --env-config config/build/env_vars_release.yaml (with the PyAuto stack on PYTHONPATH) → 0 failures; assert every on-disk fit has ~300 samples and no 2-sample simple__no_lens_light fit is created; spot-run smoke (env_vars.yaml).
Key Files
scripts/guides/results/_quick_fit.py — the single fit producer (threshold None; canonical model).
scripts/guides/results/start_here.py — results-guide entry; runs its own fit.
scripts/guides/results/aggregator/galaxies_fits.py — from_sample_index(-10) crash site.
scripts/guides/results/aggregator/samples.py — Sersic→MGE; [9] indexing.
config/build/env_vars_release.yaml — release profile (guides/results/ unsets PYAUTO_TEST_MODE).
Testing approach
The ordered guides/results release-profile run is both the reproduction and the validation harness (without --report-dir it sys.exit(1)s at the first failure; with it, it records each). Identifier equality is checked with autofit.mapper.identifier.Identifier([search, model, unique_tag]).
Original Prompt
Click to expand starting prompt
Aggregator scripts crash with IndexError (empty results) on release wheels
Type: bug
Target: autolens_workspace
Difficulty: medium
Autonomy: supervised
Priority: normal
Surfaced burning down the 2026-07-13 release-validation tail (PyAutoHeart#72). On the release wheels under the release profile, both aggregator guide scripts fail fast with the same error:
scripts/guides/results/aggregator/galaxies_fits.py ... FAIL (13.8s) IndexError: list index out of range
scripts/guides/results/aggregator/samples_via_aggregator.py ... FAIL (4.5s) IndexError: list index out of range
IndexError: list index out of range = the aggregator queried results and got an empty list, then indexed [0]. Before assuming a new bug, VERIFY it still fails on current main. Reproduce under the release profile from the autolens_workspace checkout on current main; the aggregator reads the output of a prior modeling run, so ensure that prerequisite output exists — the empty-list may be a missing/misrouted prerequisite output rather than an aggregator bug. If it reproduces: get the full traceback and fix the producer, not the [0] access. Release run: PyAutoHeart workspace-validation 29279095224, TestPyPI 2026.7.13.1.dev65601.
Investigation note (2026-07-14): reproduced on current main. Real crash site is galaxies_fits.py:176 samples.from_sample_index(sample_index=-10) → parameter_lists[-10] on a 2-element list; the shallow capped fit retained only 2 samples (no samples_weight_threshold = None), while _quick_fit's fits retain 300. See PyAutoHeart#72 cluster E.
Overview
The two
scripts/guides/results/aggregator/*.pytutorials crash withIndexError: list index out of rangeunder the release-validation profile (surfaced in the 2026-07-13 release tail, PyAutoHeart#72, cluster E). Reproduced on currentmain— it is not covered by PyAutoFit#1368 (the release profile unsetsPYAUTO_TEST_MODEforguides/results/, sois_test_mode()isFalseand the output-routing fix does not apply).Root cause: three results tutorials each run their own capped
n_like_max=300Nautilus fit, but only_quick_fit.pydisablessamples_weight_threshold. The others prune to 2 samples on disk, and the tutorials then deep-index (from_sample_index(-10),parameter_lists[9]) assuming ≥10 samples →IndexError. It is order-dependent:start_here.pyruns first and plants the 2-sample fit that the aggregator readers later choke on. The scripts' docstrings already claim they "resume from the cached fit," but their model/search config diverges from_quick_fit, so they don't — they run a separate shallow fit.Fix: consolidate onto a single fit source (
_quick_fit.py). The self-fitting scripts keep their model/search/analysis written out inline (these are teaching docs — no shared "builder" imports), but the inline definition is made to match_quick_fitsosearch.fit()genuinely resumes its 300-sample fit. Verified: the fit identifier is[search, model, unique_tag]only (analysis-independent), so a matching inline model + plainAnalysisImagingreproduces_quick_fit's on-disk identifier8bc8f101….Plan
_quick_fit.pyas the single fit producer (thresholdNone, Isothermal + shear, MGE source,AnalysisLatent); make its primary fitunique_tagsuffix-free (simple__no_lens_light) plus one more fit for the aggregator's multi-result iteration. (Bonus: fixesqueries.py, which queriesunique_tag == "simple__no_lens_light"— currently matches nothing.)start_here.py+galaxies_fits.py: addshear=al.mp.ExternalShearto the lens (they already use the identical MGE source andunique_tag=dataset_name) and match_quick_fit's identifier-affecting search fields, sosearch.fit()resumes the 300-sample fit. Deep indexing becomes valid.samples.py: swap the inlineSersicsource for the same MGE bulge + shear so it resumes the primary fit; update prose/prints describing the source.samples_via_aggregator,models,queries,data_fitting,interferometer,latent_variables) unchanged — they will only ever read 300-sample fits.guides/resultsrelease-profile run.Detailed implementation plan
Affected Repositories
Branch Survey
Suggested branch:
feature/aggregator-quick-fit-consolidationImplementation Steps
scripts/guides/results/_quick_fit.py— make the primary fitunique_tag=dataset_name(suffix-free) and keep a second distinct fit for aggregator iteration; keepconf.instance["output"]["samples_weight_threshold"] = None, the shear + MGE model,LatentShear/AnalysisLatent. Confirm identifier via the identifier harness.scripts/guides/results/start_here.py— addshear=al.mp.ExternalShearto the lensaf.Model; align theaf.Nautilusconfig with_quick_fit's identifier-affecting fields; fix the docstring (~line 104) that claims resumption. Keep the_quick_fitauto-trigger guard.scripts/guides/results/aggregator/galaxies_fits.py— same model/search alignment; it still needsdatasetfor the localal.FitImagingrefit.from_sample_index(-10)(lines ~176/238) becomes valid.scripts/guides/results/aggregator/samples.py— change sourceal.lp.Sersic→ MGE bulge (matching_quick_fit) + add shear; align search; update prose/prints referencing.source.bulge.parameter_lists[9]/log_likelihood_list[9]become valid.PYTHONPATH=../PyAutoBuild/autobuild python3 ../PyAutoBuild/autobuild/generate.py autolens.run_python.py autolens scripts/guides/results --env-config config/build/env_vars_release.yaml(with the PyAuto stack on PYTHONPATH) → 0 failures; assert every on-disk fit has ~300 samples and no 2-samplesimple__no_lens_lightfit is created; spot-run smoke (env_vars.yaml).Key Files
scripts/guides/results/_quick_fit.py— the single fit producer (threshold None; canonical model).scripts/guides/results/start_here.py— results-guide entry; runs its own fit.scripts/guides/results/aggregator/galaxies_fits.py—from_sample_index(-10)crash site.scripts/guides/results/aggregator/samples.py— Sersic→MGE;[9]indexing.config/build/env_vars_release.yaml— release profile (guides/results/unsetsPYAUTO_TEST_MODE).Testing approach
The ordered
guides/resultsrelease-profile run is both the reproduction and the validation harness (without--report-diritsys.exit(1)s at the first failure; with it, it records each). Identifier equality is checked withautofit.mapper.identifier.Identifier([search, model, unique_tag]).Original Prompt
Click to expand starting prompt
Aggregator scripts crash with IndexError (empty results) on release wheels
Type: bug
Target: autolens_workspace
Difficulty: medium
Autonomy: supervised
Priority: normal
Surfaced burning down the 2026-07-13 release-validation tail (PyAutoHeart#72). On the release wheels under the release profile, both aggregator guide scripts fail fast with the same error:
IndexError: list index out of range= the aggregator queried results and got an empty list, then indexed[0]. Before assuming a new bug, VERIFY it still fails on current main. Reproduce under the release profile from theautolens_workspacecheckout on current main; the aggregator reads the output of a prior modeling run, so ensure that prerequisite output exists — the empty-list may be a missing/misrouted prerequisite output rather than an aggregator bug. If it reproduces: get the full traceback and fix the producer, not the[0]access. Release run: PyAutoHeart workspace-validation29279095224, TestPyPI2026.7.13.1.dev65601.Investigation note (2026-07-14): reproduced on current
main. Real crash site isgalaxies_fits.py:176samples.from_sample_index(sample_index=-10)→parameter_lists[-10]on a 2-element list; the shallow capped fit retained only 2 samples (nosamples_weight_threshold = None), while_quick_fit's fits retain 300. See PyAutoHeart#72 cluster E.