From 0c9f44b940c0d95e2cd558cd2bce27da56bbf693 Mon Sep 17 00:00:00 2001 From: Tobias Edman Date: Wed, 22 Jul 2026 23:40:23 +0200 Subject: [PATCH] fix: make eclipse-check debug logging lazy and epoch-format safe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit blocks_sun() formatted the actor and epoch into an f-string on every timestep, even when no DEBUG handler was active. On some pykep builds (observed: conda-forge pykep 2.6.4, osx-arm64) str(pk.epoch) raises RuntimeError (boost bad_lexical_cast) for epochs at exact minute boundaries, e.g. str(pk.epoch(60.0 / 86400.0)) — which crashed every simulation using power devices at the first minute boundary. Use loguru's lazy opt so formatting only happens when DEBUG is emitted, and format the epoch through a fallback helper so logging can never crash the simulation even at DEBUG level. Verified: paseos/tests 32 passed, 1 pre-existing failure (thermal_model_test, fails identically on clean master). Co-Authored-By: Claude Fable 5 --- paseos/central_body/central_body.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/paseos/central_body/central_body.py b/paseos/central_body/central_body.py index d844525f..b8d0e66e 100644 --- a/paseos/central_body/central_body.py +++ b/paseos/central_body/central_body.py @@ -98,7 +98,16 @@ def blocks_sun(self, actor, t: pk.epoch, plot=False) -> bool: Returns: bool: True if the central body blocks the sun """ - logger.debug(f"Checking whether {actor} is in eclipse at {t}.") + # Lazy + safe formatting: this runs every timestep, and + # str(pk.epoch) can raise RuntimeError (boost bad_lexical_cast) + # on some pykep builds at exact minute boundaries, e.g. + # str(pk.epoch(60.0 / 86400.0)). Format only when a DEBUG + # handler is active, and never let logging crash the sim. + logger.opt(lazy=True).debug( + "Checking whether {} is in eclipse at {}.", + lambda: actor, + lambda: _safe_epoch_str(t), + ) # Compute central body position in solar reference frame r_central_body_heliocentric, _ = np.array(self._planet.eph(t)) @@ -210,3 +219,15 @@ def _apply_rotation(self, point, epoch: pk.epoch): # Rotate point q = Quaternion(axis=self._rotation_axis, angle=angle) return q.rotate(point) + +def _safe_epoch_str(t) -> str: + """String representation of a pykep epoch that cannot raise. + + Some pykep builds raise RuntimeError (boost bad_lexical_cast) in + str(epoch) for values at exact minute boundaries; fall back to the + raw mjd2000 value in that case. + """ + try: + return str(t) + except RuntimeError: + return f"epoch(mjd2000={t.mjd2000!r})"