Limitations and Known Issues When Building Mobile Apps with Tauri (iOS/Android)

Tauri mobile support is currently in alpha and requires careful handling of URI scheme registration, Rust target installations, and platform-specific configuration to avoid build failures and runtime errors.

Tauri v2 extends the framework’s Rust backend and system WebView architecture to iOS and Android, but building for mobile introduces distinct constraints not present in desktop development. Understanding these limitations and known issues when building mobile apps with Tauri is essential for avoiding silent failures and debugging complex toolchain interactions in the tauri-apps/tauri repository.

Critical Runtime Limitations

Mobile apps rely on the same core runtime as desktop, but specific timing and threading constraints apply.

URI Scheme Registration Timing

Custom URI scheme protocols must be registered before the WebView is instantiated. According to the source code in crates/tauri/src/plugin.rs (lines 601–604), if a plugin attempts to register a scheme after the WebView creation completes, the scheme will never be reachable, causing deep-links and asset loading to fail silently.

Register schemes during plugin initialization:

use tauri::{plugin::{Builder, TauriPlugin}, Runtime};

fn init<R: Runtime>() -> TauriPlugin<R> {
  Builder::new("myplugin")
    // Register early, otherwise the scheme won't be available
    .register_uri_scheme_protocol("myscheme", |_ctx, req| {
      // Example: serve a static file from the assets folder
      let path = req.uri().path().trim_start_matches('/');
      std::fs::read(path)
        .map(|data| http::Response::builder().body(data).unwrap())
        .unwrap_or_else(|_| http::Response::builder().status(404).body(Vec::new()).unwrap())
    })
    .build()
}

The registration must happen during the plugin’s init so the protocol exists when the WebView is instantiated.

iOS Async Entry Point Stability

Early versions of the mobile_entry_point macro caused panics on iOS when using async functions. This was resolved in v2.0.0-alpha.11 (see crates/tauri/CHANGELOG.md, line 453). Ensure you are running this version or later to prevent crashes when initializing async Rust code at startup.

Configuration and Setup Requirements

Mobile builds require specific toolchain components and strict configuration validation.

Required Rust Targets for Cross-Compilation

The mobile CLI commands (tauri android …, tauri ios …) require the appropriate Rust targets to be installed. As documented in packages/cli/CHANGELOG.md (commit f70b28529), the CLI now checks for these targets and aborts early if they are missing.

Install the necessary targets before running mobile commands:


# Install Android targets

rustup target add aarch64-linux-android armv7-linux-androideabi

# Install iOS targets

rustup target add aarch64-apple-ios x86_64-apple-ios

# Then run the dev command

tauri android dev   # or `tauri ios dev`

Product Name and Identifier Constraints

An empty productName in tauri.conf.json triggers a warning and can break generated Android and iOS project names, as Android package names and iOS bundle identifiers must be non-empty strings (packages/cli/CHANGELOG.md, line 113).

Additionally, changing the identifier (Android applicationId or iOS bundleIdentifier) after the mobile project has been generated can cause the CLI to fail when merging configurations, leaving stale identifiers in native project files (packages/cli/CHANGELOG.md, line 255).

Ensure your configuration is stable:

// tauri.conf.json
{
  "tauri": {
    "android": {
      "identifier": "com.example.myapp"
    }
  }
}

Android Identifier Sanitization

Using a Kotlin keyword (e.g., in, class, when) in the Android identifier previously caused ProGuard failures during the build process. The CLI now sanitizes these identifiers automatically (packages/cli/CHANGELOG.md, line 639), but providing a clean identifier avoids potential edge cases in crates/tauri-cli/src/mobile/android/android_studio_script.rs.

Platform-Specific Development Issues

Mobile development environments impose additional constraints related to simulators, permissions, and network configuration.

Xcode 16.3 and iOS Simulator Compatibility

iOS dev commands stopped working on the Xcode 16.3 simulator until the project is regenerated or the arm64-sim architecture is removed. Newer Xcode versions changed supported architectures, breaking the default project template included in earlier CLI versions (packages/cli/CHANGELOG.md, line 277).

Regenerate the iOS project after upgrading:


# Remove the problematic architecture from the project

rm -rf src-tauri/gen/apple
tauri ios init   # regenerate with the new template

Intel Mac Development Limitations

The iOS dev and build commands did not work on Intel Macs before the fix included in v2.0.0-alpha.17 (commit a9b342125). Developers on older hardware must update to this version or later to test iOS apps locally (packages/cli/CHANGELOG.md, line 134).

Android External Storage Permissions

Accessing files via convertFileSrc on Android 7+ can return 500 errors when the external storage permission is not granted. The runtime now includes better error handling and logging for this scenario (crates/tauri/CHANGELOG.md, line 26). Applications loading local media must request READ_EXTERNAL_STORAGE on older Android versions.

Dev Server Connectivity and Port Forwarding

The development server requires explicit network configuration depending on the host OS. By default on Windows, the dev server uses the public network IP; on macOS and iOS, you must explicitly enable public access using the --host flag. Misconfiguration leads to "could not connect to dev server" errors on physical devices (crates/tauri-cli/src/mobile/android/dev.rs, lines 81–96).

Additionally, the dev server port-forward on Android can fail under certain conditions, such as slow device boot sequences, though recent updates have improved resilience and logging (packages/cli/CHANGELOG.md, line 508).

Use the host flag for physical device testing:


# Use the machine's public IP so the device can reach the dev server

tauri android dev --host

# or specify an explicit address

tauri ios dev --host 192.168.1.23

Build and Distribution Constraints

Mobile app distribution requires valid signing credentials that the CLI cannot generate automatically.

Code Signing and Provisioning Requirements

iOS apps require a valid Apple developer certificate and provisioning profile, while Android apps need proper keystore configuration. The bundling step will abort if these signing keys are missing, preventing installation on physical devices or submission to app stores. Verify your signing configuration matches the platform requirements listed in the repository README.md (platform versions table).

Summary

  • Register URI schemes early in the plugin initialization phase before the WebView is created to ensure protocol availability.
  • Install required Rust targets (aarch64-linux-android, aarch64-apple-ios, etc.) before running mobile CLI commands to prevent early aborts.
  • Keep productName and identifier stable and non-empty; changes after project generation require regenerating native project files.
  • Update to v2.0.0-alpha.17 or later to resolve Intel Mac compatibility and Xcode 16.3 simulator issues.
  • Use the --host flag when testing on physical iOS or Android devices to ensure the dev server is reachable.
  • Request external storage permissions on Android when using convertFileSrc to avoid 500 errors.

Frequently Asked Questions

Why does my custom URI scheme return 404 on mobile but work on desktop?

Custom URI schemes must be registered before the WebView is instantiated. In crates/tauri/src/plugin.rs, the registration window closes once the WebView creation completes. If your plugin registers the scheme during an asynchronous setup or after the app launches, the scheme will be unreachable. Move the registration to the plugin's init function as shown in the examples above.

How do I fix "target not installed" errors when running tauri android dev?

The CLI requires specific Rust targets for cross-compilation that are not installed by default. Run rustup target add aarch64-linux-android armv7-linux-androideabi for Android or rustup target add aarch64-apple-ios for iOS. The CLI validates these targets before building (see packages/cli/CHANGELOG.md, commit f70b28529).

Why does my iOS app crash immediately on launch in Xcode 16.3?

Older project templates included an arm64-sim architecture that Xcode 16.3 no longer supports. Delete the src-tauri/gen/apple directory and run tauri ios init to regenerate the project with the updated template, as documented in the CLI changelog (line 277).

Can I use Kotlin keywords like "class" or "in" in my Android app identifier?

No. Using Kotlin reserved keywords in the Android identifier field causes ProGuard failures during the build process. While the CLI now sanitizes identifiers in crates/tauri-cli/src/mobile/android/android_studio_script.rs, you should avoid keywords entirely to prevent build ambiguity.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →