Skip to content

Commit 35c1945

Browse files
authored
Merge pull request #208 from malmeloo/fix/empty-response-management
fix: do not throw error on empty server response
2 parents b78e557 + 7c5c7d6 commit 35c1945

File tree

3 files changed

+31
-6
lines changed

3 files changed

+31
-6
lines changed

findmy/errors.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ class UnhandledProtocolError(RuntimeError):
1717
"""
1818

1919

20+
class EmptyResponseError(RuntimeError):
21+
"""
22+
Raised when Apple servers return an empty response when querying location reports.
23+
24+
This is a bug on Apple's side. More info: https://github.com/malmeloo/FindMy.py/issues/185
25+
"""
26+
27+
2028
class InvalidStateError(RuntimeError):
2129
"""
2230
Raised when a method is used that is in conflict with the internal account state.

findmy/reports/account.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
from findmy import util
3131
from findmy.errors import (
32+
EmptyResponseError,
3233
InvalidCredentialsError,
3334
InvalidStateError,
3435
UnauthorizedError,
@@ -669,8 +670,14 @@ async def _do_request() -> util.http.HttpResponse:
669670
retry_counter += 1
670671

671672
if retry_counter > 3:
672-
logger.warning("Max retries reached, returning empty response")
673-
return resp
673+
logger.warning(
674+
"Max retries reached, returning empty response. \
675+
Location reports might be missing!"
676+
)
677+
msg = "Empty response received from Apple servers. \
678+
This is most likely a bug on Apple's side. \
679+
More info: https://github.com/malmeloo/FindMy.py/issues/185"
680+
raise EmptyResponseError(msg)
674681

675682
await asyncio.sleep(2)
676683

findmy/reports/reports.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
from findmy import util
2020
from findmy.accessory import RollingKeyPairSource
21+
from findmy.errors import EmptyResponseError
2122
from findmy.keys import HasHashedPublicKey, KeyPair, KeyPairMapping, KeyPairType
2223

2324
if TYPE_CHECKING:
@@ -417,7 +418,7 @@ async def fetch_location_history(
417418

418419
return reports
419420

420-
async def _fetch_accessory_reports(
421+
async def _fetch_accessory_reports( # noqa: C901
421422
self,
422423
accessory: RollingKeyPairSource,
423424
only_latest: bool = False,
@@ -480,7 +481,10 @@ async def _fetch() -> set[LocationReport]:
480481
len(cur_keys_primary | new_keys_primary) > 290
481482
or len(cur_keys_secondary | new_keys_secondary) > 290
482483
):
483-
ret |= await _fetch()
484+
try:
485+
ret |= await _fetch()
486+
except EmptyResponseError:
487+
return []
484488

485489
# if we only want the latest report, we can stop here
486490
# since we are iterating backwards in time
@@ -498,7 +502,10 @@ async def _fetch() -> set[LocationReport]:
498502

499503
if cur_keys_primary or cur_keys_secondary:
500504
# fetch remaining keys
501-
ret |= await _fetch()
505+
try:
506+
ret |= await _fetch()
507+
except EmptyResponseError:
508+
return []
502509

503510
return sorted(ret)
504511

@@ -510,7 +517,10 @@ async def _fetch_key_reports(
510517

511518
# fetch all as primary keys
512519
ids = [([key.hashed_adv_key_b64], []) for key in keys]
513-
encrypted_reports: list[LocationReport] = await self._account.fetch_raw_reports(ids)
520+
try:
521+
encrypted_reports: list[LocationReport] = await self._account.fetch_raw_reports(ids)
522+
except EmptyResponseError:
523+
encrypted_reports = []
514524

515525
id_to_key: dict[bytes, HasHashedPublicKey] = {key.hashed_adv_key_bytes: key for key in keys}
516526
reports: dict[HasHashedPublicKey, list[LocationReport]] = {key: [] for key in keys}

0 commit comments

Comments
 (0)