From 93ad4ce587cfada290ccb2456785838d4eb6675c Mon Sep 17 00:00:00 2001 From: samlange04 Date: Sat, 3 Oct 2026 20:46:58 +0800 Subject: [PATCH 1/2] fix: DynestyDynamic crashed with OverflowError when run without an output path With `NullPaths` (a search created without a `name`), `iterations_from` returned `int(1e99)` as the "unbounded" per-chunk budget. dynesty's dynamic sampler computes `maxcall - ncall` with a numpy int64 `ncall`, and a 99-digit Python int cannot be converted to a C long, raising `OverflowError: Python int too large to convert to C long`. The static sampler only compares against `maxcall`, so it was unaffected. Use `sys.maxsize`, which is the sentinel dynesty itself uses for `maxcall=None`. Co-Authored-By: Claude Fable 5.1 --- autofit/non_linear/search/nest/dynesty/search/abstract.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/autofit/non_linear/search/nest/dynesty/search/abstract.py b/autofit/non_linear/search/nest/dynesty/search/abstract.py index 8a3d99f7d..484316e79 100644 --- a/autofit/non_linear/search/nest/dynesty/search/abstract.py +++ b/autofit/non_linear/search/nest/dynesty/search/abstract.py @@ -2,6 +2,7 @@ import logging import os +import sys from abc import ABC from pathlib import Path from typing import Dict, Optional, Tuple, Union, TYPE_CHECKING @@ -397,7 +398,12 @@ def iterations_from( if isinstance(self.paths, NullPaths): if self.maxcall is not None: return self.maxcall, self.maxcall - return int(1e99), int(1e99) + # ``sys.maxsize`` rather than ``int(1e99)``: dynesty's dynamic sampler + # computes ``maxcall - ncall`` where ``ncall`` is a numpy int64, and a + # 99-digit Python int overflows that subtraction (OverflowError: + # Python int too large to convert to C long). ``sys.maxsize`` is the + # "unbounded" sentinel dynesty itself uses when ``maxcall=None``. + return sys.maxsize, sys.maxsize try: total_iterations = np.sum(search_internal.results.ncall) From 0be8b9b27715b91d71aac450c68cb6c05822e576 Mon Sep 17 00:00:00 2001 From: samlange04 Date: Sat, 3 Oct 2026 20:58:25 +0800 Subject: [PATCH 2/2] test: DynestyStatic/DynestyDynamic NullPaths iteration budget fits a C long Regression test for the OverflowError raised by dynesty's dynamic sampler when a search is run without an output path. Co-Authored-By: Claude Fable 5.1 --- .../non_linear/search/nest/test_dynesty.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test_autofit/non_linear/search/nest/test_dynesty.py b/test_autofit/non_linear/search/nest/test_dynesty.py index 86f72372a..6eaaa2a8b 100644 --- a/test_autofit/non_linear/search/nest/test_dynesty.py +++ b/test_autofit/non_linear/search/nest/test_dynesty.py @@ -62,6 +62,29 @@ def test__explicit_params(): assert search.number_of_cores == 1 +@pytest.mark.parametrize("search_cls", [af.DynestyStatic, af.DynestyDynamic]) +def test__null_paths_iteration_budget_fits_c_long(search_cls): + """ + Without an output directory (NullPaths) the per-chunk budget is "unbounded". + It must be ``sys.maxsize``, not ``int(1e99)``: dynesty's dynamic sampler + subtracts a numpy int64 ``ncall`` from it, which raised + ``OverflowError: Python int too large to convert to C long``. + """ + import sys + from autofit.non_linear.paths.null import NullPaths + + search = search_cls() + assert isinstance(search.paths, NullPaths) + + iterations, total = search.iterations_from(MockDynestySampler(results=None)) + + assert iterations == total == sys.maxsize + assert iterations - np.int64(40) == sys.maxsize - 40 + + search = search_cls(maxcall=100) + assert search.iterations_from(MockDynestySampler(results=None)) == (100, 100) + + @pytest.mark.parametrize("search_cls", [af.DynestyStatic, af.DynestyDynamic]) def test__single_core_builds_no_pool(search_cls, monkeypatch): """