Repository navigation
Grand Slam still returns a sporadic 429, on a fresh connection #226
Description
The connection-reuse fix removed the deterministic 429. It did not remove all of them. One turned up in the app while testing the 1.1.0 build: press sign in, 429, press sign in again, straight through.
The deterministic case is real and still live at Apple
Six unauthenticated POSTs to gsa.apple.com/grandslam/GsService2 with a junk body, down one reused connection:
pooled (one reused connection): [404, 429, 429, 429, 429, 429]
The shipped path avoids that, and still sees the occasional refusal
The same six requests through FindMy.py's HttpSession, which routes gsa.apple.com through a force_close connector:
unpooled (HttpSession, shipped): [404, 404, 404, 404, 429, 404]
So the residual one is not connection reuse — every request there is a new connection. It clears on the next attempt, which is why pressing the button again works, and it is the argument for the app retrying a 429 once itself rather than presenting it as a failure. A user who does not know to press the button again reads it as the app being broken, which is how #206 arrived.
What is not established
Whether spacing the requests helps. A second run measured 1/8 refused back to back against 7/8 at 1.5-second intervals:
back to back: [404, 404, 404, 404, 404, 429, 404, 404] -> 1/8
1.5s apart: [429, 429, 429, 404, 429, 429, 429, 429] -> 7/8
That reads as spacing making it worse, and it should not be believed. The spaced arm ran second, after roughly fourteen requests had already gone out from the same address, so a rolling per-address budget explains the numbers at least as well as spacing does. The experiment has to be run in the other order, from an address that has been quiet, before either conclusion is worth anything.
One thing that is worth knowing before reading any result here: anything probing this shares an address budget with anything else signing in from the same network. A phone on the same WiFi as the machine running the probe is drawing on the same allowance, so a 429 on the phone during a probe run says nothing about the app.
Reproducing it
No account and no credentials — the edge decides on headers and connection state, so a junk body is enough. Same approach as scripts/check_gsa_edge.py.
import asyncio
from aiohttp import ClientSession, ClientTimeout, TCPConnector
from findmy.util.http import HttpSession
URL = "https://gsa.apple.com/grandslam/GsService2"
HEADERS = {
"Content-Type": "text/x-xml-plist",
"Accept": "*/*",
"User-Agent": "akd/1.0 CFNetwork/1494.0.7 Darwin/23.4.0",
"X-MMe-Client-Info":
"<MacBookPro18,3> <macOS;13.4.1;22F82> <com.apple.AuthKit/1 (com.apple.akd/1.0)>",
}
async def pooled(n=6):
async with ClientSession(connector=TCPConnector(limit=1),
timeout=ClientTimeout(total=20)) as s:
out = []
for _ in range(n):
async with s.post(URL, data=b"probe", headers=HEADERS) as r:
out.append(r.status)
return out
async def unpooled(n=6):
s, out = HttpSession(), []
try:
for _ in range(n):
out.append((await s.post(URL, data=b"probe", headers=HEADERS)).status_code)
finally:
await s.close()
return out
print("pooled ", asyncio.run(pooled()))
print("unpooled", asyncio.run(unpooled()))Interactively co-authored by Claude Code and @parawanderer
Activity
parawanderer commentedon Sep 16, 2026
Workaround for users who experience this: simply retry whatever button you tried clicking. On the app login page: just press the login button again.
This issue is open purely for the purposes of seeing if a reliable programmatic solution can be implemented for skipping this status code.
parawanderer commentedon Sep 16, 2026
Met twice in one testing session on the 1.1.0 candidate, in the iCloud setup flow rather than at sign-in: "Set up now" answered with
icloud_apple_declined_title("Apple is not answering right now"), and pressing Try Again cleared it both times.That is the same shape as the probe results above — a refusal on a fresh connection that clears immediately — and it lands on
REASON_APPLE_DECLINEDviaicloud_bridge._unexpected, which surfaces it without retrying.So the app is asking the user to do by hand, twice, what it could do itself in about a second. Worth doing, with one constraint: the retry must not cover
join. That is the only call here that writes — it enrols an escrow record and adds this app to the trust circle — and a refusal arriving after it partially succeeded, retried automatically, could enrol twice. Duplicate escrow records are precisely the noise #224 had to filter out of the recovery picker. The read-only calls (open,recovery_options,resume,fetch) have no such hazard.