> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pushctl.com/llms.txt
> Use this file to discover all available pages before exploring further.

# iOS troubleshooting

> Resolve APNs token, environment, permission, extension, and callback issues on iOS.

<AccordionGroup>
  <Accordion title="No installation appears">Confirm the Push Notifications capability, call `requestPermission`, forward both APNs success and failure callbacks, and use a Client token. Then await `waitForRegistration()` to surface the exact failure.</Accordion>
  <Accordion title="Registration times out">Confirm `AppDelegate` forwards `didRegisterForRemoteNotificationsWithDeviceToken` to `setDeviceToken` and `didFailToRegisterForRemoteNotificationsWithError` to `reportRemoteNotificationRegistrationFailure`. Test on a device with valid entitlements.</Accordion>
  <Accordion title="An APNs token exists but registration fails">Inspect the error thrown by `waitForRegistration()` or delivered to `registrationFailed`. Verify network access, the Client token, and the platform configuration in Pushctl.</Accordion>
  <Accordion title="APNs returns BadDeviceToken">Match the Pushctl environment to the installed app's `aps-environment`: development-signed Xcode builds use Sandbox, while TestFlight and App Store builds use Production. Then confirm the bundle ID and relaunch the app to register its current token. See the [iOS FAQ](/sdks/ios/faq).</Accordion>
  <Accordion title="APNs returns a 403 authentication error">Confirm the Team ID, Key ID, `.p8` key, and the key's environment and topic scope in the Apple Developer portal. Authentication failures are separate from a device token environment mismatch.</Accordion>
  <Accordion title="Received or displayed stays at zero">Add the Notification Service Extension and give both targets the identical App Group. Set `PushctlAppGroupIdentifier` in the extension.</Accordion>
  <Accordion title="The extension cannot share queued events">Confirm the App Group entitlement on both targets and the exact identifier used during initialization and in `Info.plist`.</Accordion>
  <Accordion title="Open callbacks do not fire">Assign `notificationOpened` during app startup and keep deep-link handling safe for cold launches.</Accordion>
  <Accordion title="The permission is denied">iOS does not show the permission prompt again. Direct the user to the app's notification settings.</Accordion>
  <Accordion title="Login or logout throws">Await confirmed registration first. Identity methods fail when the installation is not registered or the Pushctl API rejects the update.</Accordion>
</AccordionGroup>

<Tip>Check `subscriptionState.registrationStatus`, `registrationError`, and `isRegistered` before comparing the installation ID with the dashboard.</Tip>
