Repository navigation
Description
Steps to reproduce
- Use
google_sign_in: ^7.2.0(resolves togoogle_sign_in_android: 7.2.17) in a release build (R8 enabled). - Call
GoogleSignIn.instance.initialize()thenGoogleSignIn.instance.authenticate(). - On an affected device, pick a Google account in the Credential Manager bottom sheet.
Seen in production Crashlytics on Redmi A3, Android 16 (SDK 36). We cannot reproduce it on our own devices; it appears to depend on the credential returned by the device's Credential Manager provider.
Expected results
If the returned GoogleIdTokenCredential is missing a field that the plugin requires, authenticate() should fail with a GoogleSignInException (or the missing field should be handled), and the app should keep running.
Actual results
The app process crashes on the Credential Manager callback thread. The exception is thrown in native code on a background executor, so it cannot be caught from Dart.
Root cause
In GoogleSignInPlugin.java (Delegate.getCredential → CredentialManagerCallback.onResult), the credential is mapped like this:
new PlatformGoogleIdTokenCredential(
googleIdTokenCredential.getDisplayName(),
googleIdTokenCredential.getFamilyName(),
googleIdTokenCredential.getGivenName(),
googleIdTokenCredential.getEmail(), // @Nullable in googleid 1.2.0
googleIdTokenCredential.getUniqueId(), // @Nullable in googleid 1.2.0
googleIdTokenCredential.getIdToken(),
profilePictureUri == null ? null : profilePictureUri.toString())In com.google.android.libraries.identity.googleid:googleid:1.2.0, GoogleIdTokenCredential.getEmail() and getUniqueId() are both annotated @androidx.annotation.Nullable. However, the pigeon definition declares them as non-null:
class PlatformGoogleIdTokenCredential {
String? displayName;
String? familyName;
String? givenName;
late String email;
late String uniqueId;
late String idToken;
String? profilePictureUri;
}The generated Kotlin data class therefore has val email: String and val uniqueId: String. When either value is null, Kotlin's parameter null check fails. R8 rewrites that check to param.getClass(), which produces the NPE in the logs at Messages.kt:1.
getUniqueId() was introduced in 7.2.14 ("Uses Google Identity APIs to extract the user ID from the ID token"). getEmail() was already passed into the non-null email field in 7.2.13, so downgrading is not a reliable workaround. The code on main is unchanged.
Suggested fix: treat a null email/uniqueId as a structured failure (e.g., GetCredentialFailure with UNKNOWN or UNEXPECTED_CREDENTIAL_TYPE), or fall back to other values (e.g., getId() for the email, the sub claim of the ID token for the user ID) before constructing PlatformGoogleIdTokenCredential.
Code sample
Code sample
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
void main() => runApp(const MaterialApp(home: SignInPage()));
class SignInPage extends StatelessWidget {
const SignInPage({super.key});
Future<void> _signIn() async {
await GoogleSignIn.instance.initialize();
try {
final GoogleSignInAccount account =
await GoogleSignIn.instance.authenticate();
debugPrint('Signed in: ${account.email}');
} on GoogleSignInException catch (e) {
// Never reached: the process crashes natively before a result is returned.
debugPrint('Sign-in failed: $e');
}
}
@override
Widget build(BuildContext context) => Scaffold(
body: Center(
child: ElevatedButton(
onPressed: _signIn,
child: const Text('Sign in with Google'),
),
),
);
}Logs
Logs
Exception java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference
at io.flutter.plugins.googlesignin.PlatformGoogleIdTokenCredential.<init> (Messages.kt:1)
at io.flutter.plugins.googlesignin.GoogleSignInPlugin$Delegate$1.onResult (GoogleSignInPlugin.java:293)
at io.flutter.plugins.googlesignin.GoogleSignInPlugin$Delegate$1.onResult (GoogleSignInPlugin.java:272)
at androidx.credentials.CredentialProviderFrameworkImpl$onGetCredential$outcome$2.onResult (CredentialProviderFrameworkImpl.java:157)
at androidx.credentials.CredentialProviderFrameworkImpl$onGetCredential$outcome$2.onResult (CredentialProviderFrameworkImpl.java:150)
at android.credentials.CredentialManager$GetCredentialTransport.lambda$onResponse$1 (CredentialManager.java:809)
at android.credentials.CredentialManager$GetCredentialTransport.$r8$lambda$KZ8h0IzCqtZJ9s6sISPZis-rA-4 (CredentialManager.java)
at android.credentials.CredentialManager$GetCredentialTransport$$ExternalSyntheticLambda1.run (D8$$SyntheticClass)
at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1100)
at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:624)
at java.lang.Thread.run (Thread.java:1572)Device: Redmi A3, Android 16 (SDK 36). The stack goes through the framework android.credentials.CredentialManager (CredentialProviderFrameworkImpl), not the Play Services path.
Versions: google_sign_in 7.2.0, google_sign_in_android 7.2.17, androidx.credentials 1.6.0, googleid 1.2.0.
Flutter Doctor output
Doctor output
[√] Flutter (Channel stable, 3.44.8, on Microsoft Windows [Version 10.0.26100.8875], locale en-US) [695ms]
• Flutter version 3.44.8 on channel stable at C:\src\flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 058e0af2c2 (10 weeks ago), 2026-07-23 10:56:21 -0700
• Engine revision 0cd610717b
• Dart version 3.12.2
• DevTools version 2.57.0
• Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, no-enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration
[√] Windows Version (11 Pro 64-bit, 24H2, 2009) [2.2s]
[√] Android toolchain - develop for Android devices (Android SDK version 36.1.0) [11.8s]
• Android SDK at C:\Users\<user>\AppData\Local\Android\sdk
• Emulator version 36.6.11.0 (build_id 15507667) (CL:N/A)
• Platform android-37.0, build-tools 36.1.0
• Java binary at: C:\Program Files\Java\jdk-21\bin\java
This JDK is specified in your Flutter configuration.
To change the current JDK, run: `flutter config --jdk-dir="path/to/jdk"`.
• Java version Java(TM) SE Runtime Environment (build 21.0.2+13-LTS-58)
• All Android licenses accepted.
[X] Chrome - develop for the web (Cannot find Chrome executable at .\Google\Chrome\Application\chrome.exe) [387ms]
! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.
[!] Visual Studio - develop Windows apps (Visual Studio Community 2026 18.7.3) [386ms]
• Visual Studio at C:\Program Files\Microsoft Visual Studio\18\Community
• Visual Studio Community 2026 version 18.7.11925.98
• Windows 10 SDK version 10.0.26100.0
X Visual Studio is missing necessary components. Please re-run the Visual Studio installer for the "Desktop development with C++" workload, and include these components:
MSVC v142 - VS 2019 C++ x64/x86 build tools
- If there are multiple build tool versions available, install the latest
C++ CMake tools for Windows
Windows 10 SDK
[√] Connected device (3 available) [541ms]
• Android (mobile) • android-arm64 • Android 13 (API 33)
• Windows (desktop) • windows • windows-x64 • Microsoft Windows [Version 10.0.26100.8875]
• Edge (web) • edge • web-javascript • Microsoft Edge 154.0.4258.37
[√] Network resources [889ms]
• All expected network resources are available.
! Doctor found issues in 2 categories.
Activity
mbcorona commentedon Sep 28, 2026
Hi @AmrTawfek, thanks for the detailed report and root cause analysis.
Confirmed on main. The pigeon marks email and uniqueId as non null, but googleid 1.2.0 returns them as @nullable, so GoogleSignInPlugin.java passes null into a non null field and the Kotlin check throws the NPE you see.
Routing to team-android for further investigation.
stuartmorgan-g commentedon Sep 28, 2026
There's already a fix for this in flutter/packages#13005, since that bug became an error in Kotlin.
I'm not sure how you reached this conclusion.
getUniqueIdis both documented and annotated as non-nullable.AmrTawfek commentedon Sep 28, 2026
Thanks for linking the PR, and sorry for the confusion about getUniqueId(). The Play Console trace only showed the constructor at Messages.kt:1, without indicating which field was null, so I included both. Our crash matches the getEmail() case, so I'll follow along on #13005.
[google_sign_in] Convert implementation to Kotlin (flutter#13005)
github-actions commentedon Oct 27, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.