Capacitor 9 is a prerelease (next dist-tag, 9.0.0-alpha.x as of October 2026). Dependency ranges below target the prerelease; after 9.0.0 GA use ^9.0.0 / from: "9.0.0". Tell the user before publishing a stable plugin release that only supports a prerelease core; a common choice is to publish it under an npm next tag.
Canonical source: https://capacitorjs.com/docs/updating/plugins/9-0
When to Use
TRIGGER when:
- Plugin repo with
peerDependencies["@capacitor/core"]at^8or>=8and the user wants Capacitor 9 support - Plugin fails to compile against Capacitor 9 on removed APIs (
CAPBridge,@NativePlugin,saveCall,getWebView(),isSimulator()) - Plugin's
android/build.gradlefails under AGP 9 / Gradle 9 (jcenter(),kotlin-android,proguard-android.txt, namespace collision) - A consuming app without Cordova plugins fails on the plugin's
CordovaSPM product orcom.getcapacitor.cordovaimports
Do not use:
- App projects ->
capacitor-app-upgrade-v8-to-v9 - Plugin still on 7 or older ->
capacitor-plugin-upgrades(chain majors) - Adding SPM to a CocoaPods-only plugin ->
capacitor-plugin-spm-support - Only checking a plugin against the 8.5 UIScene lifecycle ->
capacitor-uiscene-migration(references/plugin-audit.md)
Live Project Snapshot
!node -e "const fs=require('fs');if(!fs.existsSync('package.json'))process.exit(0);const pkg=JSON.parse(fs.readFileSync('package.json','utf8'));const out=['package.name='+(pkg.name||''),'package.version='+(pkg.version||'')];for(const section of ['peerDependencies','dependencies','devDependencies']){for(const [name,version] of Object.entries(pkg[section]||{})){if(name.startsWith('@capacitor/'))out.push(section+'.'+name+'='+version)}}out.push('Package.swift='+fs.existsSync('Package.swift'));out.push('podspec='+fs.readdirSync('.').filter(f=>f.endsWith('.podspec')).join(','));console.log(out.join('\n'))"
!find . -maxdepth 3 \( -path './example-app' -o -path './example' -o -path './ios' -o -path './android' \) -not -path './node_modules/*'
Procedure
- Inspect. Read the snapshot,
android/build.gradle,android/gradle.properties, the.podspec,Package.swift, and list native sources (android/src/main,ios/Sourcesorios/Plugin). Note the example app path. Confirm the tree is clean (git status). - Run the migrator from the plugin root:
Review the diff (npx @capacitor/plugin-migration-v8-to-v9@latestgit diff). It covers most file edits, not API removals in your code. - Dependencies in
package.json:devDependencies:@capacitor/cli,@capacitor/core,@capacitor/android,@capacitor/ios->next.peerDependencies["@capacitor/core"]:>=9.0.0-alpha.6(checknpm view @capacitor/core dist-tagsfor the current prerelease). Ask whether the release should still support 8; most plugins drop it because iOS 16 / AGP 9 build changes are not backward compatible.
- Build files per
references/build-files.md(gradle.properties,build.gradle, podspec,Package.swift). Keep both podspec andPackage.swift: apps on CocoaPods and SPM both consume the plugin. - Code API removals. Grep, then fix each hit with
references/android-api-removals.mdandreferences/ios-api-removals.md. Do not leave deprecated call paths behind#ifor reflection. - Cordova optionality. Remove the unconditional
.product(name: "Cordova", ...)fromPackage.swift. If the plugin's native code imports Cordova compatibility classes (com.getcapacitor.cordova.*,CDV*) it will break in apps without Cordova plugins; ask the user how to replace it. - UIScene lifecycle. Every Capacitor 9 app is scene-based. Audit iOS code for AppDelegate-method assumptions,
tmpWindow,keyWindowpresentation,applicationState(seecapacitor-uiscene-migration->references/plugin-audit.md). Since the minimum is now 9,.capacitorScene*notifications andSceneDelegateProxyare safe to use. - Example app and docs. Upgrade the example app with
capacitor-app-upgrade-v8-to-v9. Update README install/compat tables (Capacitor 9, iOS 16, minSdk 26). - Verify with
references/verification.md. Bump the plugin major version.
Traps
- AGP 9 defaults
android.uniquePackageNames=true: a scaffold default namespace (com.mycompany.plugins.example) or a fork that kept the upstream namespace now fails the consuming app's build. Make it unique. targetSdkVersionin a library module has no runtime effect; delete it rather than bumping.CapacitorUrlRequest.setRequestHeaders([String: Any])sets values instead of appending; repeated header keys now overwrite.Package.swiftmust point atcapacitor-swift-pmfrom: "9.0.0-alpha.6"or later (earlier alphas had Cordova-optionality crashes). Use the newest alpha.googleMapsUtilsVersion5.0.0 carries upstream breaking API changes.- Running
npx cap syncfrom the plugin root does nothing useful; sync inside the example app.
Error Handling
| Error | Fix |
|---|---|
cannot find symbol ... class NativePlugin |
@CapacitorPlugin(name = ..., permissions = ...) |
cannot find symbol ... method saveCall(PluginCall) |
call.setKeepAlive(true) or bridge.saveCall(call) |
cannot find symbol ... method pluginRequestPermission(...) |
requestPermissionForAlias(alias, call, "callbackName") + @PermissionCallback |
Cannot find 'CAPBridge' in scope |
ApplicationDelegateProxy.shared / Notification.Name.capacitorStatusBarTapped |
Value of type 'CAPBridgeProtocol' has no member 'getWebView' |
bridge?.webView (same pattern for other getters -> properties) |
| Duplicate or conflicting Kotlin plugin error under AGP 9 | Remove standalone Kotlin plugin and stdlib |
| Namespace collision / duplicate package in consuming app | Unique namespace in android/build.gradle |
SPM resolution or link error mentioning Cordova in a consuming app |
Remove the Cordova product dependency |
References
Only load a reference when its topic is in play.
| File | Load when |
|---|---|
references/build-files.md |
Editing gradle.properties, build.gradle, podspec, Package.swift, wrapper |
references/android-api-removals.md |
Any Java/Kotlin compile error or grep hit |
references/ios-api-removals.md |
Any Swift/ObjC compile error or grep hit |
references/verification.md |
After edits: greps, builds, example-app checks, publish |
Related skills: capacitor-plugin-upgrades, capacitor-app-upgrade-v8-to-v9, capacitor-uiscene-migration, capacitor-plugin-spm-support.