Merge pull request #208 from malmeloo/fix/empty-response-management

fix: do not throw error on empty server response
This commit is contained in:
Mike Almeloo
2025-11-17 21:57:56 +01:00
committed by GitHub
3 changed files with 31 additions and 6 deletions

View File

@@ -17,6 +17,14 @@ class UnhandledProtocolError(RuntimeError):
""" """
class EmptyResponseError(RuntimeError):
"""
Raised when Apple servers return an empty response when querying location reports.
This is a bug on Apple's side. More info: https://github.com/malmeloo/FindMy.py/issues/185
"""
class InvalidStateError(RuntimeError): class InvalidStateError(RuntimeError):
""" """
Raised when a method is used that is in conflict with the internal account state. Raised when a method is used that is in conflict with the internal account state.

View File

@@ -29,6 +29,7 @@ from typing_extensions import ParamSpec, override
from findmy import util from findmy import util
from findmy.errors import ( from findmy.errors import (
EmptyResponseError,
InvalidCredentialsError, InvalidCredentialsError,
InvalidStateError, InvalidStateError,
UnauthorizedError, UnauthorizedError,
@@ -669,8 +670,14 @@ class AsyncAppleAccount(BaseAppleAccount):
retry_counter += 1 retry_counter += 1
if retry_counter > 3: if retry_counter > 3:
logger.warning("Max retries reached, returning empty response") logger.warning(
return resp "Max retries reached, returning empty response. \
Location reports might be missing!"
)
msg = "Empty response received from Apple servers. \
This is most likely a bug on Apple's side. \
More info: https://github.com/malmeloo/FindMy.py/issues/185"
raise EmptyResponseError(msg)
await asyncio.sleep(2) await asyncio.sleep(2)

View File

@@ -18,6 +18,7 @@ from typing_extensions import override
from findmy import util from findmy import util
from findmy.accessory import RollingKeyPairSource from findmy.accessory import RollingKeyPairSource
from findmy.errors import EmptyResponseError
from findmy.keys import HasHashedPublicKey, KeyPair, KeyPairMapping, KeyPairType from findmy.keys import HasHashedPublicKey, KeyPair, KeyPairMapping, KeyPairType
if TYPE_CHECKING: if TYPE_CHECKING:
@@ -417,7 +418,7 @@ class LocationReportsFetcher:
return reports return reports
async def _fetch_accessory_reports( async def _fetch_accessory_reports( # noqa: C901
self, self,
accessory: RollingKeyPairSource, accessory: RollingKeyPairSource,
only_latest: bool = False, only_latest: bool = False,
@@ -480,7 +481,10 @@ class LocationReportsFetcher:
len(cur_keys_primary | new_keys_primary) > 290 len(cur_keys_primary | new_keys_primary) > 290
or len(cur_keys_secondary | new_keys_secondary) > 290 or len(cur_keys_secondary | new_keys_secondary) > 290
): ):
ret |= await _fetch() try:
ret |= await _fetch()
except EmptyResponseError:
return []
# if we only want the latest report, we can stop here # if we only want the latest report, we can stop here
# since we are iterating backwards in time # since we are iterating backwards in time
@@ -498,7 +502,10 @@ class LocationReportsFetcher:
if cur_keys_primary or cur_keys_secondary: if cur_keys_primary or cur_keys_secondary:
# fetch remaining keys # fetch remaining keys
ret |= await _fetch() try:
ret |= await _fetch()
except EmptyResponseError:
return []
return sorted(ret) return sorted(ret)
@@ -510,7 +517,10 @@ class LocationReportsFetcher:
# fetch all as primary keys # fetch all as primary keys
ids = [([key.hashed_adv_key_b64], []) for key in keys] ids = [([key.hashed_adv_key_b64], []) for key in keys]
encrypted_reports: list[LocationReport] = await self._account.fetch_raw_reports(ids) try:
encrypted_reports: list[LocationReport] = await self._account.fetch_raw_reports(ids)
except EmptyResponseError:
encrypted_reports = []
id_to_key: dict[bytes, HasHashedPublicKey] = {key.hashed_adv_key_bytes: key for key in keys} id_to_key: dict[bytes, HasHashedPublicKey] = {key.hashed_adv_key_bytes: key for key in keys}
reports: dict[HasHashedPublicKey, list[LocationReport]] = {key: [] for key in keys} reports: dict[HasHashedPublicKey, list[LocationReport]] = {key: [] for key in keys}