Repository navigation
Description
Priority
- High
- Medium
- Low
Plugin(s) affected
@capacitor/local-notifications
Current problem behavior
Every JS call into LocalNotifications (e.g. LN.requestPermissions(), LN.checkPermissions(), LN.schedule()) rejects on iOS with:
Unhandled Promise Rejection: Error: "LocalNotifications.then()" is not implemented on ios
The .then() variant of the "not implemented" error (rather than the expected LN.requestPermissions() is not implemented) suggests Capacitor's proxy is falling back to the web implementation, which for LocalNotifications uses a chunked async import(...).then(e => new e.LocalNotificationsWeb). Something in that async chain routes back through the native bridge and fails.
No iOS permission dialog ever appears. Notifications never fire.
Expected behavior
LN.requestPermissions() shows the iOS permission dialog, resolves to a permission state, and LN.schedule() queues notifications with iOS.
Steps to reproduce
- Capacitor 8.4.2 iOS app with SPM setup (
npx cap add ios --packagemanager SPM) npm install @capacitor/local-notifications@8.2.1npx cap sync ios- Add
NSUserNotificationsUsageDescriptionto Info.plist - Call
LocalNotifications.requestPermissions()from JS - Observe the "not implemented" error in the console; no permission dialog appears
What we've verified (rules out common causes)
- Plugin class IS in the compiled binary —
strings ios/App/App/Build/.../App.debug.dylib | grep LocalNotificationsPluginreturns matches. Dead-code stripping ruled out. capacitor.config.jsonpackageClassListcontains"LocalNotificationsPlugin"— autogenerated bycap sync, unmodified.- JS bundle correctly registers the plugin proxy —
registerPlugin("LocalNotifications", { web: () => import(...).then(...) })appears in the built ESM chunk. - 6 other Capacitor npm plugins in the SAME setup auto-register fine and work:
@capacitor/preferences,@capacitor/browser,@capacitor/camera,@capgo/capacitor-social-login,@ebarooni/capacitor-calendar,@aparajita/capacitor-biometric-auth. Same auto-discovery mechanism, same Info.plist workflow, same everything. Only@capacitor/local-notificationsfails.
What we tried that didn't help
- Skipping
checkPermissions()and callingrequestPermissions()directly (in case of an iOS 26checkPermissionshang) — same "not implemented" result. - Force-linking plugin imports in
AppDelegate.swift— no effect (class was already in the binary). - Custom
MyViewController: CAPBridgeViewControllersubclass withbridge?.registerPluginInstance(LocalNotificationsPlugin())incapacitorDidLoad—capacitorDidLoadwas verified never called (NSLog missing from Xcode Debug Area) even with@objc(MyViewController)on the class andcustomClass="MyViewController" customModule="App" customModuleProvider="target"in the storyboard. - Uninstall + reinstall + Clean Build Folder — no change.
Environment
- @capacitor/core: 8.4.2
- @capacitor/local-notifications: 8.2.1
- @capacitor/cli: 8.4.2
- @capacitor/ios: 8.4.2
- iOS deployment target: 17.0
- Xcode: 26.6
- Device: iPhone 17 Pro Max, iOS 26.6
Ask
Is there a reason @capacitor/local-notifications's auto-discovery via packageClassList + NSClassFromString("LocalNotificationsPlugin") fails when the class is present in the binary, and the other Capacitor npm plugins in the same setup succeed? Any known workaround for Capacitor 8.4.2 SPM users?
Activity
jcesarmobile commentedon Aug 24, 2026
Local notifications plugin has been moved to https://github.com/ionic-team/capacitor-local-notifications, please, report the issue on https://github.com/ionic-team/capacitor-local-notifications/issues
Also, latest plugin version is 8.3.1 and latest Capacitor is 8.5.0, so would be good to test with latest versions.
If the problem persists, create a new ticket on the mentioned repository and provide a sample app that reproduces the issue.
ionitron-bot commentedon Sep 8, 2026
Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of the plugin, please create a new issue and ensure the template is fully filled out.