1
0
mirror of https://github.com/home-assistant/supervisor.git synced 2026-05-24 08:38:48 +01:00

Log unexpected errors in api_process wrappers (#6739)

* Log unexpected errors in api_process wrappers

The `api_process` and `api_process_raw` decorators silently swallowed
any `HassioError` that bubbled up from endpoint handlers, returning
`"Unknown error, see Supervisor logs"` to the caller while logging
nothing. This made the response message actively misleading: e.g. when
an endpoint touching D-Bus hit `DBusNotConnectedError` (raised without
a message by `@dbus_connected`), Core would surface
`SupervisorBadRequestError: Unknown error, see Supervisor logs` and
the Supervisor logs would contain no trace of it.

Log the caught `HassioError` with traceback before delegating to
`api_return_error` so the "see Supervisor logs" hint is actually
actionable. The `APIError` branch is left alone — those carry explicit
status codes and messages set by Supervisor code and are already
visible in the response.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Capture unexpected API errors to Sentry

Non-APIError HassioError exceptions reaching api_process indicate
missing error handling in the endpoint handler. In addition to the
logging added in the previous commit, also send these to Sentry so
they surface as actionable issues rather than silently returning
"Unknown error, see Supervisor logs" to the caller.

* Drop capture exception from set_boot_slot

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Agner
2026-04-21 16:04:39 +02:00
committed by GitHub
parent 7fb621234e
commit ff2cdbfc36
2 changed files with 8 additions and 2 deletions
+8
View File
@@ -3,6 +3,7 @@
import asyncio
from collections.abc import Callable, Mapping
import json
import logging
from typing import Any, cast
from aiohttp import web
@@ -31,8 +32,11 @@ from ..jobs import JobSchedulerOptions, SupervisorJob
from ..utils import check_exception_chain, get_message_from_exception_chain
from ..utils.json import json_dumps, json_loads as json_loads_util
from ..utils.log_format import format_message
from ..utils.sentry import async_capture_exception
from . import const
_LOGGER: logging.Logger = logging.getLogger(__name__)
def extract_supervisor_token(request: web.Request) -> str | None:
"""Extract Supervisor token from request."""
@@ -72,6 +76,8 @@ def api_process(method):
err, status=err.status, job_id=err.job_id, headers=err.headers
)
except HassioError as err:
_LOGGER.exception("Unexpected error during API call: %s", err)
await async_capture_exception(err)
return api_return_error(err)
if isinstance(answer, (dict, list)):
@@ -119,6 +125,8 @@ def api_process_raw(content, *, error_type=None):
job_id=err.job_id,
)
except HassioError as err:
_LOGGER.exception("Unexpected error during API call: %s", err)
await async_capture_exception(err)
return api_return_error(
err, error_type=error_type or const.CONTENT_TYPE_BINARY
)
-2
View File
@@ -22,7 +22,6 @@ from ..exceptions import (
)
from ..jobs.const import JobConcurrency, JobCondition
from ..jobs.decorator import Job
from ..utils.sentry import async_capture_exception
from .data_disk import DataDisk
_LOGGER: logging.Logger = logging.getLogger(__name__)
@@ -363,7 +362,6 @@ class OSManager(CoreSysAttributes):
RaucState.ACTIVE, self.get_slot_name(boot_name)
)
except DBusError as err:
await async_capture_exception(err)
raise HassOSSlotUpdateError(
f"Can't mark {boot_name} as active!", _LOGGER.error
) from err