From c05e66669e30eb5d5933f1bc8d9f692a1d477da9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 1 May 2026 12:09:00 -0500 Subject: [PATCH] [api] Tidy decoder warning when EsphomeError has no message _run_idedata raises EsphomeError() with no message, so the warning shows 'unavailable ()' which looks like a bug. Use a generic fallback explanation when str(exc) is empty. --- esphome/components/api/client.py | 9 ++++++--- tests/unit_tests/components/api/test_client.py | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/esphome/components/api/client.py b/esphome/components/api/client.py index 9b8b42ab31..d5214ccbf6 100644 --- a/esphome/components/api/client.py +++ b/esphome/components/api/client.py @@ -68,10 +68,13 @@ class _LogLineProcessor: except EsphomeError as exc: self._decode_enabled = False self.backtrace_state = False + # _run_idedata raises EsphomeError with no message; fall back + # to a generic explanation when str(exc) is empty. + detail = str(exc) or "build artifacts not found locally" _LOGGER.warning( - "Crash trace decoding unavailable (%s). Run " - "'esphome compile' for this device to enable PC decoding.", - exc, + "Crash trace decoding unavailable: %s. " + "Run 'esphome compile' for this device to enable PC decoding.", + detail, ) diff --git a/tests/unit_tests/components/api/test_client.py b/tests/unit_tests/components/api/test_client.py index 1e16c5ebbc..3970d1ce8b 100644 --- a/tests/unit_tests/components/api/test_client.py +++ b/tests/unit_tests/components/api/test_client.py @@ -42,6 +42,21 @@ def test_decoder_swallows_platform_handler_error() -> None: assert processor.backtrace_state is False +def test_decoder_warning_uses_fallback_for_empty_error(caplog) -> None: + """_run_idedata raises EsphomeError with no message; the warning + must show a useful explanation rather than empty parens. + """ + config = {"esphome": {"name": "test"}} + processor = api_client._LogLineProcessor(config, None) + + with patch.object(api_client, "process_stacktrace", side_effect=EsphomeError()): + processor.process_line("PC: 0x4010496e") + + warnings = [r.message for r in caplog.records if r.levelname == "WARNING"] + assert any("build artifacts not found locally" in m for m in warnings) + assert not any("()" in m for m in warnings) + + def test_decoder_short_circuits_after_failure() -> None: """After one failure, subsequent lines must not retry the decoder.