From 05a58d476895fe265435a5af7021db774f43e812 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 3 Feb 2026 11:12:37 +0100 Subject: [PATCH] Add exception handling for pull progress tracking errors (#6516) * Add exception handling for pull progress tracking errors Wrap progress event processing in try-except blocks to prevent image pulls from failing due to progress tracking issues. This ensures that progress updates, which are purely informational, never abort the actual Docker pull operation. Catches two categories of exceptions: - ValueError: Includes "Cannot update a job that is done" errors that can occur under rare event combinations (similar to #6513) - All other exceptions: Defensive catch-all for any unexpected errors in the progress tracking logic All exceptions are logged with full context (layer ID, status, progress) and sent to Sentry for tracking and debugging. The pull continues successfully in all cases. Co-Authored-By: Claude Sonnet 4.5 * Apply suggestions from code review Co-authored-by: Mike Degatano * Apply suggestions from code review --------- Co-authored-by: Claude Sonnet 4.5 Co-authored-by: Mike Degatano --- supervisor/docker/interface.py | 39 ++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/supervisor/docker/interface.py b/supervisor/docker/interface.py index e40d6d0d8..5a8651184 100644 --- a/supervisor/docker/interface.py +++ b/supervisor/docker/interface.py @@ -240,14 +240,39 @@ class DockerInterface(JobGroup, ABC): if event.job_id != current_job.uuid: return - # Process event through progress tracker - pull_progress.process_event(event) + try: + # Process event through progress tracker + pull_progress.process_event(event) - # Update job if progress changed significantly (>= 1%) - should_update, progress = pull_progress.should_update_job() - if should_update: - stage = pull_progress.get_stage() - current_job.update(progress=progress, stage=stage) + # Update job if progress changed significantly (>= 1%) + should_update, progress = pull_progress.should_update_job() + if should_update: + stage = pull_progress.get_stage() + current_job.update(progress=progress, stage=stage) + except ValueError as err: + # Catch ValueError from progress tracking (e.g. "Cannot update a job + # that is done") which can occur under rare event combinations. + # Log with context and send to Sentry. Continue the pull anyway as + # progress updates are informational only. + _LOGGER.warning( + "Received an unprocessable update for pull progress (layer: %s, status: %s, progress: %s): %s", + event.id, + event.status, + event.progress, + err, + ) + await async_capture_exception(err) + except Exception as err: # pylint: disable=broad-except + # Catch any other unexpected errors in progress tracking to prevent + # pull from failing. Progress updates are informational - the pull + # itself should continue. Send to Sentry for debugging. + _LOGGER.warning( + "Error updating pull progress (layer: %s, status: %s): %s", + event.id, + event.status, + err, + ) + await async_capture_exception(err) listener = self.sys_bus.register_event( BusEvent.DOCKER_IMAGE_PULL_UPDATE, process_pull_event