Skip to content

Give the exporter's requests thirty seconds, as the app already has - #122

Merged
parawanderer merged 1 commit into
mainfrom
fix/exporter-login-timeout
Aug 20, 2026
Merged

Give the exporter's requests thirty seconds, as the app already has#122
parawanderer merged 1 commit into
mainfrom
fix/exporter-login-timeout

Conversation

@parawanderer

Copy link
Copy Markdown
Owner

The Android app raised this a release ago. The exporter was left on FindMy.py's default of five seconds per request, and nothing here ever passed the parameter that commit made settable.

Five is a cap on one request, and the exporter makes many. A sign-in is several round trips, and what follows is heavier than the sign-in: escrow recovery, then the CloudKit fetches that carry the actual keys. A link slow enough to spend five seconds on any one of them fails partway through, as a bare timeout naming no cause.

Three call sites

Where Why it is separate
A first run's account
A later run's account, restored from the stored identity The path nearly every export takes, and the one a fix applied to the obvious call site would miss
RemoteAnisetteProvider Its own session. The Anisette fetch happens inside the login but from the provider's own client, so raising the account's does nothing for it

LocalAnisetteProvider takes no timeout and is not given one — there is no HTTP in it to spend one on. It is also the default here, so this is about Apple's own hosts, and about --anisette-url for anyone who does point it at a server.

Testing

Five tests, asserting on what the call passes rather than on FindMy.py's internals: the value lands on a private session attribute with no accessor, and a test reaching in there breaks on a rename that changed nothing real. What can actually regress is this module forgetting to pass it, since the default is silent.

Verified by removing each of the three call sites, which reddens one, one and two respectively. One test also pins that the raised value is still above upstream's default, so a future release raising its own past thirty would be a downgrade nothing else here would notice.

How it was found

Writing the 1.3.0 release notes, where I had listed it as an exporter fix on the strength of the app's commit touching python/. It touched pyproject.toml and uv.lock — the pin that makes the parameter exist — and nothing that passes it. The note was wrong; this makes it true.

Separately: python/.venv was two revisions stale (102dd8e rather than the pinned 23a9b8d), which is why the parameter looked absent at first. uv sync --frozen fixes it, and the full suite passes on the correct pin.


PR description summarised by Claude Code.

The Android app raised this a release ago; the exporter was left on FindMy.py's
default of five seconds per request, and nothing here ever passed the parameter
that commit made settable. Two halves of one project disagreeing about how
patient this protocol needs somebody to be.

**Five is a cap on one request, and this makes many.** A sign-in is several
round trips, and what follows it is heavier than the sign-in: escrow recovery,
then the CloudKit fetches that carry the actual keys. A link slow enough to
spend five seconds on any one of them fails partway through, as a bare timeout
naming no cause.

Passed in three places because there are three constructions, and only some of
them are on the path any given run takes:

- a first run's account
- a later run's account, restored from the stored identity - which is the one
  nearly every export goes through, and the one a fix applied to the obvious
  call site would miss
- `RemoteAnisetteProvider`, which has its own session, so raising the account's
  does nothing for it. The Anisette fetch happens inside the login but from the
  provider's own client.

`LocalAnisetteProvider` takes no timeout and is not given one; there is no HTTP
in it to spend it on. It is also the default here - Anisette is generated on
this machine - so this is about Apple's own hosts, and about `--anisette-url`
for anyone who does point it at a server.

Five tests, asserting on what the call passes rather than on FindMy.py's
internals: the value lands on a private session attribute with no accessor, and
a test reaching in there breaks on a rename that changed nothing real. What can
regress is this module forgetting to pass it, since the default is silent.
Verified by removing each of the three, which reddens one, one and two.

One of them pins that the raised value is still above upstream's default, so a
future release raising its own past thirty would be a downgrade nothing else
here would notice.

Found while writing the 1.3.0 release notes, where it had been listed as an
exporter fix on the strength of the app's commit touching python/. It touched
`pyproject.toml` and `uv.lock` - the pin that makes the parameter exist - and
nothing that passes it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@parawanderer
parawanderer merged commit fde310c into main Aug 20, 2026
5 checks passed
@parawanderer
parawanderer deleted the fix/exporter-login-timeout branch August 20, 2026 08:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant