Fix Apple ID sign in failing with a 3840 plist parse error - #49
Open
Calvin-Zikakis wants to merge 2 commits into
Open
Fix Apple ID sign in failing with a 3840 plist parse error#49Calvin-Zikakis wants to merge 2 commits into
Calvin-Zikakis wants to merge 2 commits into
Conversation
sendAuthenticationRequest() handed the GSA response body straight to PropertyListSerialization without checking that the server actually sent a plist. When gsa.apple.com returns an HTML error page — it serves one from its own edge, e.g. a 401 "Authorization Required" page with Server: Apple — the parse failure was forwarded verbatim, surfacing as NSCocoaErrorDomain 3840 "Encountered unknown tag html on line 1". AltServer wraps that as "could not sign in with your Apple ID", which reads as a credential or anisette problem rather than a server error. ALTAppleAPI.m already maps a failed parse to NSURLErrorBadServerResponse for the non-auth endpoints; the auth path was the outlier. Add a propertyListResponse() helper used by the GsService2 handler and the trusted-device 2FA verify handler, which had the same blind parse. It parses first and only enriches on failure, rather than gating on the status code: a status gate cannot catch HTML returned with a 200, and GSA mirrors its status into the body as Status.hsc alongside ec/em, so bailing out before reading the body risks masking real error codes such as -20101. Parsing first also means no currently-working request changes behaviour. On failure the error becomes NSURLErrorBadServerResponse carrying the original parse error as NSUnderlyingErrorKey, plus the status, Content-Type and a 256-byte body snippet in NSDebugDescriptionErrorKey. Reported in altstoreio/AltStore#1776, #1699 and #1747.
This was referenced Sep 4, 2026
Apple's GSA edge keeps a keep-alive connection pinned to a backend node.
When that node starts failing, every subsequent request on the same
connection returns 5xx and never recovers. Measured on an affected Mac,
six requests over one reused connection:
200 200 503 503 503 503
200 503 503 503 503 503
200 200 200 200 503 503
while six requests each on a fresh connection fail independently at
roughly half:
503 200 503 503 503 200
200 503 503 200 200 503
ALTAppleAPI keeps a single session for every request, so authenticate()
sends init, complete and apptokens down one connection. init and complete
go through, the connection sours, and apptokens gets an HTML 503 that
surfaces as NSCocoaErrorDomain 3840. That matches the reports exactly, and
explains why the failure looked specific to apptokens when it is really
just whichever request lands after the connection goes bad.
Retry 5xx up to five times with exponential backoff, giving each attempt
its own session so it opens a new connection. Retrying on the shared
session is useless here, since every attempt inherits the same dead node.
Verified on a machine that had never once completed sign in: all three
calls returned 200 and apptokens returned its token on the first attempt.
Reported in altstoreio/AltStore#1776, #1699 and #1747.
This was referenced Sep 4, 2026
Calvin-Zikakis
force-pushed
the
fix/gsa-html-response-marketplace
branch
from
September 4, 2026 06:17
9199500 to
a91fb9e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Sign in fails with
NSCocoaErrorDomain 3840 "Encountered unknown tag html on line 1", which AltServer shows as "could not sign in with your Apple ID". Reported in altstoreio/AltStore#1776, #1699, #1747.What happens
Sign in makes three calls to GsService2. Apple returns an HTML error page for some of them, and
sendAuthenticationRequest()hands the body straight toPropertyListSerializationwith no check, so a server error surfaces as a parse failure that reads like bad credentials.Apple's edge also pins a connection to a backend node, and once that node starts failing every later request on the same connection fails too.
ALTAppleAPIuses one session for everything, so all three calls share a connection and whichever request lands after it sours is the one that dies. That is why this looks specific to apptokens when it is not.Changes
Retry 5xx up to five times with backoff, each attempt on its own session so it opens a new connection. Retrying on the shared session does nothing, every attempt inherits the same dead node.
Report a failed parse as
NSURLErrorBadServerResponsewith the status, Content-Type and a body snippet instead of the raw 3840.ALTAppleAPI.malready does this for the other endpoints. The same helper covers the trusted device 2FA handler, which had the identical blind parse.It parses first and only builds the better error on failure, rather than gating on the status code. A status check misses HTML served with a 200, and GSA reports its own status in the body as
Status.hsc, so returning early could hide real error codes. Parsing first also means nothing that works today changes.Numbers
25 full sign in attempts per row, on an affected Mac:
#47 does most of the work here and is worth taking alongside this. I said earlier that the User-Agent looked unrelated, which was wrong, that came from a sample far too small to see the effect.
Testing
AltServer built with this signed in first try on a machine that had never once completed it, and installed AltStore. Builds clean.
Branches
marketplaceandnotarizedhave diverged and neither contains the other. AltStore's classic branches pinnotarized, so #50 is this same fix for that side. Both are needed.#48 found the parse problem independently against
master, which looks dormant, HEAD is from July 2020.