Skip to content

iOS capability sync silently swallows App Store Connect API errors and reports success #3986

Description

@jean-losi

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 <store-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.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions