Summary
VehicleManager.update_all_vehicles_with_cached_state iterates over all vehicles with no per-vehicle error handling. The first vehicle that raises aborts the entire loop, and the exception propagates up to Home Assistant as ConfigEntryNotReady.
The practical consequence: one vehicle the backend no longer serves makes every other vehicle in the account permanently unavailable, even when their data was fetched successfully moments earlier in the same cycle.
def update_all_vehicles_with_cached_state(self) -> None:
for vehicle_id in self.vehicles:
self.update_vehicle_with_cached_state(vehicle_id) # first raise ends everything
Concrete case (Hyundai EU, 2 vehicles on one account)
- Vehicle A (2026,
ccuCCS2ProtocolSupport: 1) → retCode: 'S', full CCS2 payload, valid data
- Vehicle B (2023,
protocolType: 0) → retCode: 'F', resCode: '5031', "Unavailable remote control - Service Temporary Unavailable"
Vehicle B was sold and is no longer owned, but is still listed on the Bluelink account and cannot currently be removed via the app. It is unlikely to ever return a successful response again.
Debug logging over several setup cycles showed a clean 1:1 alternation — 6 successful get_cached_vehicle_status responses and 6 × 5031, i.e. exactly one success and one failure per cycle. Vehicle A is fetched successfully every single time, and its data is then discarded because vehicle B raises immediately afterwards.
Log line (redacted):
DEBUG [hyundai_kia_connect_api.KiaUvoApiEU] get_cached_vehicle_status response:
{'retCode': 'F', 'resCode': '5031', 'resMsg': 'Unavailable remote control - Service Temporary Unavailable', ...}
Resulting Home Assistant state: Config Not Ready: Unavailable remote control - Service Temporary Unavailable, retried indefinitely, zero entities for either vehicle.
Versions: kia_uvo v3.10.1, hyundai_kia_connect_api 4.26.5 (both current; login/WAF handling from 4.26.3 works correctly here — the vehicle list is fetched without any problem).
Why this is distinct from #1774 (kia_uvo)
In kia_uvo#1774, 5031 is explained as a transient server-side outage where retrying is the correct behaviour. That reasoning is sound for a single-vehicle account, and this report does not dispute it.
The separate issue here is the blast radius: when 5031 is permanent for one vehicle, retrying never converges, and healthy vehicles are taken down with it. That is a robustness property of the loop, independent of which vehicle fails or why.
Suggested fix
Isolate failures per vehicle, and only raise when no vehicle could be updated — so a genuine full outage is still reported rather than silently swallowed:
def update_all_vehicles_with_cached_state(self) -> None:
last_error = None
updated = 0
for vehicle_id in list(self.vehicles):
try:
self.update_vehicle_with_cached_state(vehicle_id)
updated += 1
except Exception as err:
last_error = err
_LOGGER.warning("Skipping vehicle, cached update failed: %s", err)
if updated == 0 and last_error is not None:
raise last_error
update_vehicle_with_cached_state already honours if vehicle.enabled:, so an alternative (or complement) would be for the integration to expose disable_vehicle() — currently it exists in the library (VehicleManager, line ~350) but is never called from kia_uvo, leaving users with no supported way to skip a dead vehicle.
The same pattern applies to force_refresh_all_vehicles_states and check_and_force_update_vehicles.
I am running the per-vehicle isolation above as a local patch in coordinator.py and it resolves the situation — the working vehicle reports normally while the dead one is logged and skipped. Happy to open a PR against the library if the approach looks right to you.
Summary
VehicleManager.update_all_vehicles_with_cached_stateiterates over all vehicles with no per-vehicle error handling. The first vehicle that raises aborts the entire loop, and the exception propagates up to Home Assistant asConfigEntryNotReady.The practical consequence: one vehicle the backend no longer serves makes every other vehicle in the account permanently unavailable, even when their data was fetched successfully moments earlier in the same cycle.
Concrete case (Hyundai EU, 2 vehicles on one account)
ccuCCS2ProtocolSupport: 1) →retCode: 'S', full CCS2 payload, valid dataprotocolType: 0) →retCode: 'F', resCode: '5031', "Unavailable remote control - Service Temporary Unavailable"Vehicle B was sold and is no longer owned, but is still listed on the Bluelink account and cannot currently be removed via the app. It is unlikely to ever return a successful response again.
Debug logging over several setup cycles showed a clean 1:1 alternation — 6 successful
get_cached_vehicle_statusresponses and 6 ×5031, i.e. exactly one success and one failure per cycle. Vehicle A is fetched successfully every single time, and its data is then discarded because vehicle B raises immediately afterwards.Log line (redacted):
Resulting Home Assistant state:
Config Not Ready: Unavailable remote control - Service Temporary Unavailable, retried indefinitely, zero entities for either vehicle.Versions:
kia_uvov3.10.1,hyundai_kia_connect_api4.26.5 (both current; login/WAF handling from 4.26.3 works correctly here — the vehicle list is fetched without any problem).Why this is distinct from #1774 (kia_uvo)
In kia_uvo#1774,
5031is explained as a transient server-side outage where retrying is the correct behaviour. That reasoning is sound for a single-vehicle account, and this report does not dispute it.The separate issue here is the blast radius: when
5031is permanent for one vehicle, retrying never converges, and healthy vehicles are taken down with it. That is a robustness property of the loop, independent of which vehicle fails or why.Suggested fix
Isolate failures per vehicle, and only raise when no vehicle could be updated — so a genuine full outage is still reported rather than silently swallowed:
update_vehicle_with_cached_statealready honoursif vehicle.enabled:, so an alternative (or complement) would be for the integration to exposedisable_vehicle()— currently it exists in the library (VehicleManager, line ~350) but is never called fromkia_uvo, leaving users with no supported way to skip a dead vehicle.The same pattern applies to
force_refresh_all_vehicles_statesandcheck_and_force_update_vehicles.I am running the per-vehicle isolation above as a local patch in
coordinator.pyand it resolves the situation — the working vehicle reports normally while the dead one is logged and skipped. Happy to open a PR against the library if the approach looks right to you.