· via dev.to (home feed)
Apple blocks app-specific-password IPA uploads, breaking Windows and Linux CI pipelines
Apple ID plus app-specific-password IPA uploads now fail at Apple's gateway with error -22938; the documented fix is migrating CI pipelines to the App Store Connect Build Uploads API.

IPA uploads that sign in with an Apple ID and an app-specific password began failing around October 28, according to a detailed write-up on dev.to. The change breaks Windows and Linux CI pipelines that push builds with tools such as ios-uploader or custom scripts, while Xcode and Apple's official Transporter app continue to work normally.
What broke
According to the dev.to post, upload tools that authenticate with an Apple ID plus an app-specific password now fail at the login step. Instead of the JSON response the client expects, Apple's upload authentication endpoint returns plain text telling the user to sign in with the app-specific password they generated, ending in error code -22938. Scripts that parse the reply as JSON tend to crash with a parse error such as 'Unexpected token S', which makes the failure look like a client-side bug rather than a change on Apple's side.
Credentials are not the problem
The developer behind the post verified that the same app-specific password still authenticates against Apple's CalDAV endpoint, which returns HTTP 207. That rules out expired or mistyped credentials and points at the upload service itself.
A long list of experiments narrowed it down further. Plain and gzip-compressed request bodies, HTTP/1.1 and HTTP/2, the JSON-RPC endpoint, the SOAP endpoint, User-Agent strings mimicking iTMSTransporter 4.2.0 and 4.3.1 plus Transporter 5.0, an App Store Connect API key JWT sent as a myacinfo cookie or a Bearer token, and an alternate content delivery host all produced the same login prompt. Even a deliberately nonexistent JSON-RPC method name returned the identical message, which means requests are rejected at the gateway before they reach the backend service; the reported response headers show Server: daiquiri/5 with an instance tag of 26HOTFIX47.
The conclusion in the post is that Apple closed the Apple-ID-plus-app-specific-password login path at the gateway, and no client-side parameter change will restore it.
The replacement: the Build Uploads API
The recommended fix is App Store Connect's documented Build Uploads resource, which authenticates with an API key (JWT) and never touches the blocked endpoints. The flow:
- POST /v1/buildUploads creates an upload, taking the version, build number and platform.
- POST /v1/buildUploadFiles returns presigned object-storage upload URLs.
- The IPA is sent to the presigned URL with PUT requests, in 5 MB chunks.
- PATCH /v1/buildUploadFiles/{id} marks the file as uploaded.
Apple then parses the build, and it shows up in TestFlight and App Store Connect. One gotcha the author flags: the valid assetType values are ASSET, ASSET_DESCRIPTION and ASSET_SPI, not IPA.
What you need to migrate
Switching requires an App Store Connect API key with the App Manager role or higher, generated under Users and Access, then Integrations. The .p8 private key file can be downloaded only once, and the Key ID and Issuer ID have to be recorded alongside it. You also need the app's numeric App ID, which appears in the App Store Connect URL after apps/.
The author packaged the whole flow into a zero-dependency Node.js CLI called asc-ipa-uploader, published on GitHub, that runs on Windows, macOS and Linux using only built-in modules. It checks whether a build number already exists before transferring anything, retries the transient 401 responses that brand-new API keys can trigger while Apple propagates them, uploads in chunks with progress output, and polls until the build reaches VALID. In the author's test, a 17 MB IPA uploaded and reached VALID in about two minutes. The tool can optionally create the App Store version and attach the build afterwards.
The usual cautions apply: never commit the .p8 file (the CLI also reads credentials from environment variables), and Apple rejects duplicate build numbers, so the build number has to be bumped for a re-upload.
Why it matters
First, the change removes an authentication path that non-Mac CI pipelines have quietly depended on. Teams building iOS apps on Windows or Linux runners, without Xcode or the official Transporter app, now have to provision App Store Connect API keys and rewrite their upload steps. There is nothing to patch in existing scripts, because the rejection happens before the request ever reaches the upload service.
Second, it is a reminder of the risk in building on undocumented login flows. The Apple-ID-plus-app-specific-password route was never a documented upload API, and Apple was able to close it at the gateway from one day to the next. The dev.to post makes no mention of advance notice from Apple, and it remains one developer's diagnosis rather than a confirmed statement from the company.
Third, the migration lands teams on the supported path, which is arguably better anyway: scoped and revocable API keys instead of personal Apple ID credentials, resumable chunked uploads, and status polling until the build is valid.
- #ios
- #ci-cd
- #app-store-connect
- #testflight
- #apple