# Flutter: “Unhandled Exception: PlatformException(…)”

> Flutter throws PlatformException when a plugin’s native side fails. Read its code, then fix sign_in_failed, channel-error and denied access.

Canonical: https://app369.com/fix/flutter-platformexception/
Last updated: 2026-11-08

The app logs Unhandled Exception: PlatformException(sign_in_failed, …), PlatformException(channel-error, …) or another code, usually after a plugin call such as Google sign-in, the camera, a file picker or Firebase. PlatformException is not one bug. It is how a plugin reports that its Android or iOS side failed, and the first value in the brackets, the code, tells you which failure it was.

**Short answer**

Read the code, the first value inside PlatformException( ). sign_in_failed with ApiException: 10 means the app’s SHA-1 fingerprint is missing in Firebase. channel-error means the plugin’s native side isn’t registered: stop the app and rebuild it, because hot restart doesn’t add native code. An access-denied code from a camera or photo plugin means the user said no; offer a way to the app’s settings. Wrap the plugin call in try / on PlatformException so a failure shows a message instead of crashing the screen.

## **What the code means, and the fix**

1. 01 ### **Read the code, message and details**
  > “Thrown to indicate that a platform interaction failed in the platform plugin.” [**Flutter, PlatformException class**](https://api.flutter.dev/flutter/services/PlatformException-class.html) Every PlatformException carries a code, a message and optional details. The code is set by the plugin, so search for it in that plugin’s docs or issues, not in Flutter’s. Catch it around the plugin call and log all three, so the next failure tells you which case you hit.```
try {
  final file = await ImagePicker().pickImage(source: ImageSource.camera);
} on PlatformException catch (e) {
  debugPrint('code: ${e.code} message: ${e.message} details: ${e.details}');
  // show the user a message instead of a red screen
}
```
2. 02 ### **sign_in_failed with ApiException: 10** Google Sign-In on Android fails with code 10 when the SHA-1 fingerprint of the key that signed the build isn’t in the Firebase project, or google-services.json is out of date. The debug key, the upload key and the Play app signing key each need their own fingerprint. The full fix is on the Google Sign-In DEVELOPER_ERROR page linked below. Code 12500 usually points at an incomplete OAuth consent screen (a missing support email), and code 7 at the network.
3. 03 ### **channel-error: Unable to establish connection on channel**
  > “a PlatformException, if the invocation failed in the platform plugin” [**Flutter, MethodChannel.invokeMethod**](https://api.flutter.dev/flutter/services/MethodChannel/invokeMethod.html) The Dart side called a plugin whose native side isn’t there. This happens after adding or upgrading a plugin and only hot restarting, after mixing plugin versions (one FlutterFire package upgraded without the others), or when Firebase.initializeApp() hasn’t finished before the first Firebase call. Stop the app, run flutter clean and flutter pub get (and pod install on iOS), upgrade related plugins together, and await initializeApp() in main() before runApp(). In unit and widget tests there is no native side at all, so mock the plugin there.```
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(const MyApp());
}
```
4. 04 ### **Camera or photo access denied**
  > “Add the following keys to your Info.plist file, located in <project root>/ios/Runner/Info.plist:” [**pub.dev, image_picker**](https://pub.dev/packages/image_picker) Camera, photo and location plugins throw a PlatformException, such as camera_access_denied, when the user declines the permission prompt. Catch it and show a message with a way to open the app’s settings, because once the user has said no for good the prompt won’t show again. On Android, check the permission is declared in AndroidManifest.xml. On iOS, add the usage keys to ios/Runner/Info.plist before testing: without them iOS stops the app outright instead of throwing, and App Store Connect rejects the build (ITMS-90683).```
<key>NSCameraUsageDescription</key>
<string>Take a photo for your profile.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Choose a photo for your profile.</string>
```

Checked against the vendor’s docs on November 8, 2026: [Flutter API: PlatformException class](https://api.flutter.dev/flutter/services/PlatformException-class.html); [Flutter API: MethodChannel.invokeMethod (when a plugin call throws)](https://api.flutter.dev/flutter/services/MethodChannel/invokeMethod.html); [pub.dev: image_picker (iOS Info.plist keys)](https://pub.dev/packages/image_picker).

## **Rather hand it over?**

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

- [from $450**App Fix Ticket**One reproducible bug in an existing mobile or web app, diagnosed and fixed.**See scope and start**](https://app369.com/fixed-price/flutter-firebase-bug-fix/)
- [from $450**AI-Built App Rescue**A Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.****No issues worth fixing, no charge.**** If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.**See scope and start**](https://app369.com/fixed-price/ai-app-rescue/)

Related: [**Google Sign-In DEVELOPER_ERROR on Android**](https://app369.com/fix/firebase-google-sign-in-android-developer-error/) · [**Flutter MissingPluginException**](https://app369.com/fix/flutter-missingpluginexception/) · [**ITMS-90683: missing purpose string**](https://app369.com/fix/itms-90683-missing-purpose-string/) · [**Flutter “type 'Null' is not a subtype of type 'String'”**](https://app369.com/fix/flutter-type-null-is-not-a-subtype-of-type-string/)

Questions

## **More on this error**

<details>

<summary>**Why does it only happen in the release build? **+</summary>

Release builds are signed with a different key and shrunk by R8. A sign_in_failed that only shows in release usually means the release or Play app signing SHA-1 is missing in Firebase. Other codes can come from R8 removing plugin classes; check the plugin’s docs for ProGuard rules.

</details>

<details>

<summary>**Is PlatformException the same as MissingPluginException? **+</summary>

No. PlatformException means the native side ran and reported a failure. MissingPluginException means no native code answered the call at all, usually because the app wasn’t rebuilt after adding the plugin.

</details>

<details>

<summary>**Can you fix it for me? **+</summary>

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.

</details>

A different error?

## **Describe it and get a written quote**

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; Simon replies by email, usually within one business day.

[**Describe your problem **→](https://app369.com/contact/) [**All fixes**](https://app369.com/fix/)