Bug Report
Plugin(s)
@capacitor/http 7.2.0
@capacitor/ios 7.2.0
Capacitor Version
💊 Capacitor Doctor 💊
Latest Dependencies:
@capacitor/cli: 7.2.0
@capacitor/core: 7.2.0
@capacitor/android: 7.2.0
@capacitor/ios: 7.2.0
Installed Dependencies:
@capacitor/cli: 5.7.8
@capacitor/core: 5.7.8
@capacitor/android: 5.7.8
@capacitor/ios: 5.7.8
[success] iOS looking great! 👌
[success] Android looking great! 👌
Platform(s)
IOS
Current Behavior
When using the latest versions of all @capacitor/ packages (core, cli, ios) and installing the latest standalone @capacitor/http plugin, the Xcode build fails after running npx cap sync.
The specific error is:
.../node_modules/@capacitor/http/ios/Plugin/Plugin.m:4:1: error: duplicate interface definition for class 'CAPHttpPlugin'
The build log indicates the "previous definition is here" pointing to a path within the core Capacitor.framework/Headers/Capacitor-Swift.h. This strongly suggests that the native code for the HTTP plugin is now bundled within the core @capacitor/ios framework, and the pod specification from the standalone @capacitor/http package is creating a conflict.
Expected Behavior
The Xcode project should build successfully after installing @capacitor/http and running npx cap sync. The JavaScript bridge provided by the @capacitor/http npm package should allow for native HTTP requests to be made without native build conflicts.
Code Reproduction
A minimal reproduction can likely be created with the following steps:
Create a new project with a web framework (e.g., SvelteKit, Next.js, or even a simple HTML/JS setup).
Initialize Capacitor in the project: npx cap init [appName] [appId]
Install the latest Capacitor core dependencies:
npm install @capacitor/cli@latest @capacitor/core@latest @capacitor/ios@latest
Install the latest official HTTP plugin:
npm install @capacitor/http@latest
Add the iOS platform:
npx cap add ios
Sync the project:
npx cap sync
Open the generated iOS project in Xcode:
npx cap open ios
Attempt to build the project for a simulator or device.
Other Technical Details
Node.js Version: v22.14.0
NPM Version: 10.9.2
Xcode Version: Version 16.3
macOS Version: Sequoia 15.3.1
Project Framework: SvelteKit with Vite (though the issue appears to be at the native iOS build level, independent of the web framework).
Additional Context
This issue was encountered during an extensive debugging process to enable native HTTP requests for a Supabase backend, specifically to bypass CORS issues in a Capacitor mobile app (as Supabase seems to have removed UI-based CORS configuration for wildcard origins like capacitor://localhost).
Key Observations from Debugging:
The Podfile generated by npx cap sync correctly includes the line pod 'CapacitorHttp', :path => '../../node_modules/@capacitor/http' when the @capacitor/http npm package is installed.
The Xcode error message explicitly points to the Plugin.m from the CapacitorHttp pod and the Capacitor-Swift.h from the core Capacitor.framework as the sources of the duplicate definition.
Workaround 1 (Native Build Success, Runtime JS Failure): Manually removing the pod 'CapacitorHttp' line from the Podfile (after npx cap sync) and then running pod install allows the native Xcode project to build successfully. However, this breaks the JavaScript bridge:
If the @capacitor/http npm package is uninstalled (to prevent npx cap sync from re-adding the pod line), then import { CapacitorHttp } from '@capacitor/http'; fails, and Capacitor.Plugins.Http is undefined at runtime.
If the @capacitor/http npm package is installed but the pod line is manually removed, import { CapacitorHttp } from '@capacitor/http'; (static or dynamic) still results in an undefined plugin object at runtime, suggesting the JS bridge relies on the pod being registered.
Successful Workaround (Using Older Capacitor Ecosystem): The only way to achieve a working application (both build and runtime) was to downgrade the entire Capacitor ecosystem to version 5 and use the older @capacitor-community/http@^1 plugin with a dynamic import() in JavaScript:
Bash
npm install @capacitor/cli@5 @capacitor/core@5 @capacitor/ios@5 @capacitor/android@5 @capacitor/preferences@5 @capacitor-community/http@^1
And in the client-side JavaScript:
JavaScript
// Inside an async function on a native platform
const { Http } = await import('@capacitor-community/http');
await Http.request(...);
This strongly suggests an issue specific to the latest (v6+) versions of Capacitor and how the @capacitor/http plugin interacts with the core @capacitor/ios framework.
Bug Report
Plugin(s)
@capacitor/http 7.2.0
@capacitor/ios 7.2.0
Capacitor Version
💊 Capacitor Doctor 💊
Latest Dependencies:
@capacitor/cli: 7.2.0
@capacitor/core: 7.2.0
@capacitor/android: 7.2.0
@capacitor/ios: 7.2.0
Installed Dependencies:
@capacitor/cli: 5.7.8
@capacitor/core: 5.7.8
@capacitor/android: 5.7.8
@capacitor/ios: 5.7.8
[success] iOS looking great! 👌
[success] Android looking great! 👌
Platform(s)
IOS
Current Behavior
When using the latest versions of all @capacitor/ packages (core, cli, ios) and installing the latest standalone @capacitor/http plugin, the Xcode build fails after running npx cap sync.
The specific error is:
.../node_modules/@capacitor/http/ios/Plugin/Plugin.m:4:1: error: duplicate interface definition for class 'CAPHttpPlugin'
The build log indicates the "previous definition is here" pointing to a path within the core Capacitor.framework/Headers/Capacitor-Swift.h. This strongly suggests that the native code for the HTTP plugin is now bundled within the core @capacitor/ios framework, and the pod specification from the standalone @capacitor/http package is creating a conflict.
Expected Behavior
The Xcode project should build successfully after installing @capacitor/http and running npx cap sync. The JavaScript bridge provided by the @capacitor/http npm package should allow for native HTTP requests to be made without native build conflicts.
Code Reproduction
A minimal reproduction can likely be created with the following steps:
Create a new project with a web framework (e.g., SvelteKit, Next.js, or even a simple HTML/JS setup).
Initialize Capacitor in the project: npx cap init [appName] [appId]
Install the latest Capacitor core dependencies:
npm install @capacitor/cli@latest @capacitor/core@latest @capacitor/ios@latest
Install the latest official HTTP plugin:
npm install @capacitor/http@latest
Add the iOS platform:
npx cap add ios
Sync the project:
npx cap sync
Open the generated iOS project in Xcode:
npx cap open ios
Attempt to build the project for a simulator or device.
Other Technical Details
Node.js Version: v22.14.0
NPM Version: 10.9.2
Xcode Version: Version 16.3
macOS Version: Sequoia 15.3.1
Project Framework: SvelteKit with Vite (though the issue appears to be at the native iOS build level, independent of the web framework).
Additional Context
This issue was encountered during an extensive debugging process to enable native HTTP requests for a Supabase backend, specifically to bypass CORS issues in a Capacitor mobile app (as Supabase seems to have removed UI-based CORS configuration for wildcard origins like capacitor://localhost).
Key Observations from Debugging:
The Podfile generated by npx cap sync correctly includes the line pod 'CapacitorHttp', :path => '../../node_modules/@capacitor/http' when the @capacitor/http npm package is installed.
The Xcode error message explicitly points to the Plugin.m from the CapacitorHttp pod and the Capacitor-Swift.h from the core Capacitor.framework as the sources of the duplicate definition.
Workaround 1 (Native Build Success, Runtime JS Failure): Manually removing the pod 'CapacitorHttp' line from the Podfile (after npx cap sync) and then running pod install allows the native Xcode project to build successfully. However, this breaks the JavaScript bridge:
If the @capacitor/http npm package is uninstalled (to prevent npx cap sync from re-adding the pod line), then import { CapacitorHttp } from '@capacitor/http'; fails, and Capacitor.Plugins.Http is undefined at runtime.
If the @capacitor/http npm package is installed but the pod line is manually removed, import { CapacitorHttp } from '@capacitor/http'; (static or dynamic) still results in an undefined plugin object at runtime, suggesting the JS bridge relies on the pod being registered.
Successful Workaround (Using Older Capacitor Ecosystem): The only way to achieve a working application (both build and runtime) was to downgrade the entire Capacitor ecosystem to version 5 and use the older @capacitor-community/http@^1 plugin with a dynamic import() in JavaScript:
Bash
npm install @capacitor/cli@5 @capacitor/core@5 @capacitor/ios@5 @capacitor/android@5 @capacitor/preferences@5 @capacitor-community/http@^1
And in the client-side JavaScript:
JavaScript
// Inside an async function on a native platform
const { Http } = await import('@capacitor-community/http');
await Http.request(...);
This strongly suggests an issue specific to the latest (v6+) versions of Capacitor and how the @capacitor/http plugin interacts with the core @capacitor/ios framework.