iOS capability sync silently swallows App Store Connect API errors and reports success
- Dominant language
- TypeScript
- Stars
- 1.4k
- Forks
- 236
- Avg merge
- 3d 1h
- Merged PRs (30d)
- 91
Description
### Summary
`syncCapabilitiesForEntitlementsAsync` (`build/credentials/ios/appstore/bundleIdCapabilities.js`) wraps `bundleId.updateBundleIdCapabilityAsync(modifiedRequest)` in a try/catch whose catch block only re-throws when the error message matches one specific pattern (`/bundle '[\w\d]+' cannot be deleted. Delete all the Apps/`). **Every other Apple API error is silently discarded**, and the function still returns the full `enabled`/`disabled` name lists — so the CLI prints:
```
✔ Synced capabilities: Enabled: Associated Domains
```
…even when Apple rejected the request and nothing was persisted.
Verified in **eas-cli 18.12.3** and **20.5.1** (same code in both).
### What happened to us
After adding `ios.associatedDomains` to our app config, every App Store build failed at Xcode signing for 12 days (`Provisioning profile … doesn't include the Associated Domains capability`). Running `eas build` interactively (authenticated via ASC API key env vars) reported `✔ Synced capabilities: Enabled: Associated Domains` on **three separate runs**, yet `GET /v1/bundleIds/{id}/bundleIdCapabilities` showed the capability was never enabled, and freshly regenerated provisioning profiles still lacked the entitlement.
Calling the same mutation ourselves surfaced the swallowed error — Apple rejects the PATCH `/v1/bundleIds/{id}` relationship payload that `@expo/apple-utils` sends:
```
HTTP 400 — The request entity is not a valid request document object -
Unexpected or invalid value at 'data.relationships.bundleIdCapabilities.data.[0].attributes'.
```
The documented `POST /v1/bundleIdCapabilities` shape (with a `bundleId` relationship) works and returns 201; after enabling the capability that way, the next `eas build` regenerated the profile correctly.
### Expected behavior
1. A failed capability PATCH should fail the sync (or at minimum log the Apple error) instead of printing `✔ Synced capabilities: Enabled: …`. The current catch turns a hard signing failure into a false success and makes the incident undebuggable from CLI output.
2. Ideally the capability update itself should use the documented `POST /v1/bundleIdCapabilities` request shape, which Apple currently accepts.
### Environment
- eas-cli 18.12.3 and 20.5.1 (`@expo/apple-utils` 2.1.11 in 18.12.3)
- Auth: App Store Connect API key (ADMIN role) via `EXPO_ASC_API_KEY_PATH` / `EXPO_ASC_KEY_ID` / `EXPO_ASC_ISSUER_ID`
- Capability involved: `ASSOCIATED_DOMAINS` (plain boolean capability, no settings)
### Repro sketch
1. Take an app whose App ID lacks Associated Domains and whose stored App Store profile predates it.
2. Add `ios.associatedDomains: ["applinks:example.com"]` to the app config.
3. Run `eas build -p ios --profile ` with ASC API key env vars (interactive).
4. Observe `✔ Synced capabilities: Enabled: Associated Domains`, then check the App ID via the ASC API — the capability is not enabled, and the regenerated profile lacks `com.apple.developer.associated-domains`.
Contributor guide
Assessment
This issue has not been assessed yet.