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
- 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.
- 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
- Take an app whose App ID lacks Associated Domains and whose stored App Store profile predates it.
- Add
ios.associatedDomains: ["applinks:example.com"] to the app config.
- Run
eas build -p ios --profile <store-profile> with ASC API key env vars (interactive).
- 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.
Summary
syncCapabilitiesForEntitlementsAsync(build/credentials/ios/appstore/bundleIdCapabilities.js) wrapsbundleId.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 fullenabled/disabledname lists — so the CLI prints:…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.associatedDomainsto our app config, every App Store build failed at Xcode signing for 12 days (Provisioning profile … doesn't include the Associated Domains capability). Runningeas buildinteractively (authenticated via ASC API key env vars) reported✔ Synced capabilities: Enabled: Associated Domainson three separate runs, yetGET /v1/bundleIds/{id}/bundleIdCapabilitiesshowed 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-utilssends:The documented
POST /v1/bundleIdCapabilitiesshape (with abundleIdrelationship) works and returns 201; after enabling the capability that way, the nexteas buildregenerated the profile correctly.Expected behavior
✔ Synced capabilities: Enabled: …. The current catch turns a hard signing failure into a false success and makes the incident undebuggable from CLI output.POST /v1/bundleIdCapabilitiesrequest shape, which Apple currently accepts.Environment
@expo/apple-utils2.1.11 in 18.12.3)EXPO_ASC_API_KEY_PATH/EXPO_ASC_KEY_ID/EXPO_ASC_ISSUER_IDASSOCIATED_DOMAINS(plain boolean capability, no settings)Repro sketch
ios.associatedDomains: ["applinks:example.com"]to the app config.eas build -p ios --profile <store-profile>with ASC API key env vars (interactive).✔ Synced capabilities: Enabled: Associated Domains, then check the App ID via the ASC API — the capability is not enabled, and the regenerated profile lackscom.apple.developer.associated-domains.