From b3467e97b77ea1f6c751359c16b5af152786cc4f Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Fri, 23 Jan 2026 17:43:03 +0000 Subject: [PATCH] fix(sonos): Gracefully handle failure when fetching device state #455 --- src/backend/sources/SonosSource.ts | 39 +++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/backend/sources/SonosSource.ts b/src/backend/sources/SonosSource.ts index ddab9bdf..93f5e023 100644 --- a/src/backend/sources/SonosSource.ts +++ b/src/backend/sources/SonosSource.ts @@ -22,6 +22,7 @@ import { FixedSizeList } from "fixed-size-list"; import { buildStatePlayerPlayIdententifyingInfo, hashObject, parseArrayFromMaybeString } from "../utils/StringUtils.js"; import { isDebugMode, playObjDataMatch, sleep } from "../utils.js"; import { playContentInvariantTransform } from "../utils/PlayComparisonUtils.js"; +import dayjs, { Dayjs } from "dayjs"; export interface DeviceState { device: SonosDevice @@ -60,6 +61,8 @@ export class SonosSource extends MemoryPositionalSource { groupsAllow: string[] = []; groupsBlock: string[] = []; + protected badDeviceError: Record = {}; + constructor(name: any, config: SonosSourceConfig, internal: InternalConfig, emitter: EventEmitter) { const { data, @@ -151,7 +154,41 @@ export class SonosSource extends MemoryPositionalSource { const playerStates: PlayerStateData[] = []; for (const d of this.manager.Devices) { - const state = await d.GetState(); + let state: SonosState; + try { + state = await d.GetState(); + } catch (e) { + if(e instanceof Error) { + let muted = false, + seen = false; + if(this.badDeviceError[d.Name] !== undefined) { + seen = this.badDeviceError[d.Name].err === e.message; + if(seen && this.badDeviceError[d.Name].time !== undefined && Math.abs(this.badDeviceError[d.Name].time.diff(dayjs(), 's')) < 60) { + muted = true; + } + } + if(muted) { + // already logged in the last minute + continue; + } + if(seen) { + // already logged full error, just log that its still happening + this.logger.debug(`Could not get Device '${d.Name}' state due to already seen error. Will mute for 1 minute => ${e.message}`); + this.badDeviceError[d.Name] = {err: e.message, time: dayjs()}; + continue; + } + this.logger.warn(new Error(`Could not get Device '${d.Name}' state`, {cause: e})); + this.badDeviceError[d.Name] = {err: e.message}; + continue; + } else { + this.logger.error(new Error(`Uncaught exception of unknown type when getting Device '${d.Name}' state`, {cause: e})); + continue; + } + } + // clear any state errors for this device + if(this.badDeviceError[d.Name] !== undefined) { + delete this.badDeviceError[d.Name]; + } const x = { state, device: d -- 2.51.2