Flutterfire: iOS - Linking anonymous account with email provider results in exception "The method '[]' was called on null."

Created on 9 Dec 2019  路  9Comments  路  Source: FirebaseExtended/flutterfire

The problem

I am attempting to link an anonymous user with an email/password credential and I am consistently getting this exception thrown

NoSuchMethodError: The method '[]' was called on null.
Receiver: null
Tried calling: []("isNewUser")

the relevant flutter code:

Future<FirebaseUser> linkWithEmailPassword(String email, String password) async {
    AuthCredential credential = EmailAuthProvider.getCredential(email: email, password: password);
    AuthResult auth = await currentUser.linkWithCredential(credential);
    if (auth.user != null) {
      print("Linking accounts succeeded");
      return auth.user;
    } else {
      print("** /n/n LINKING ANONYMOUS ACCOUNT FAILED /n/n **");
      return null;
    }
  }

neither of my print statements above ever execute, I get an exception from Firebase, which I am catching, and that's where it stops. In other words, the call to Firebase's linkWithCredential is what is returning an error.

I am also double checking that currentUser is indeed anonymous.

One strange thing about this is that a new email/password account is created every time. Sometimes the accounts are even linked, but not in every case.

I am using:

cloud_firestore: ^0.12.11
firebase_auth: ^0.15.1
firebase_storage: ^3.0.8

What I am not doing

I am not creating a new user with the credentials before trying to link them. I tried that for fun and it always gives me back an error about the account already being linked to that provider type, but never this exception.

What I have tried

flutter clean
flutter pub get

pod update Firebase/Firestore
pod update Firebase/FirebaseAuth

I have tried downgrading cloud firestore 0.12.0 since someone said their crash started in 0.12.11, but that didn't work either

Flutter Doctor

Doctor summary (to see all details, run flutter doctor -v):
[鉁揮 Flutter (Channel dev, v1.13.0, on Mac OS X 10.14.6 18G84, locale en-US)

[!] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    ! Some Android licenses not accepted.  To resolve this, run: flutter doctor --android-licenses
[鉁揮 Xcode - develop for iOS and macOS (Xcode 11.1)
[鉁揮 Android Studio (version 3.5)
[鉁揮 VS Code (version 1.32.1)
[鉁揮 Connected device (1 available)

! Doctor found issues in 1 category.
regression bug

Most helpful comment

oh whoops I meant to respond to the update
@hterkelsen same as the previous comment, running flutter pub upgrade solved the issue for me. Things are working great!

thanks for the lightning fast response to this one! 馃帀

All 9 comments

In my case simple anonymous login fails with the same error message, only in iOS. I think the root of the problem is that firebase_auth_platform_interface doesn't prepared for null additionalUserInfo. The interface was implemented for flutter web compatibility. The plugin was fixed in version 0.12.0 to handle null additionalUserInfo, so downgrading firebase_auth is a possible workaround. The interface was added in 0.15.0+2.
firebase_auth: 0.15.0+1works for me.

PlatformAuthResult _decodeAuthResult(Map<dynamic, dynamic> data) {
  final PlatformUser user = _decodeUser(data['user']);
  final PlatformAdditionalUserInfo additionalUserInfo =
      _decodeAdditionalUserInfo(data['additionalUserInfo']);
  return PlatformAuthResult(user: user, additionalUserInfo: additionalUserInfo);
}

PlatformAdditionalUserInfo _decodeAdditionalUserInfo(
    Map<dynamic, dynamic> data) {
  return PlatformAdditionalUserInfo(
    isNewUser: data['isNewUser'],    **// IF data == null EXCEPTION**
    username: data['username'],
    providerId: data['providerId'],
    profile: data['profile']?.cast<String, dynamic>(),
  );

}

Hi @erparker
can you please provide your flutter run --verbose?
Also, to better address the issue, would be helpful
if you could post a minimal code sample
or the steps to reproduce the problem.
Thank you

I posted the code in my original question that's giving me the error. Basically I have an anonymous user and I try to link with an email credential and then this exception happens. I'll post some more code for added context.

Here's the --verbose error. The first line is my code preparing to make the link call and the last line is the exception I get from the library.
verbose-error.txt

My plan is to allow users to have an anonymous login and later convert to a permanent user. So on app launch I am checking for any user, if I don't find one I login anonymously, and I keep a reference to the current user in a helper class:

class FirebaseAuthMethods {
  static final FirebaseAuthMethods instance = FirebaseAuthMethods._private();

  FirebaseAuthMethods._private();

  factory FirebaseAuthMethods() => instance;

  final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;

  FirebaseUser currentUser;

...  

Future<FirebaseUser> anonymousLogin() async {
    try {
      AuthResult auth = await _firebaseAuth.signInAnonymously();
      print("anonymous login with user: ${auth.user}");
      currentUser = auth.user;
      return currentUser;
    } catch (e) {
      print("error doing anonymous login: $e");
    }
    return null;
  }

Later on my login/signup page I am simply gathering the user's email and password, creating a credential, and then trying to link the anonymous account with the email/password credential. I am checking to see if the user is indeed anonymous before trying to link the accounts, and the user always is.

if (widget.auth.currentUser.isAnonymous == true) {
            print("account is anonymous, attempting link");
            await widget.auth.linkWithEmailPassword(_email, _password);
          } else {
            print("attempting to sign up new user, not anonymous");
            userId = await widget.auth.signUp(_email, _password);
            print("signed up new user: $userId");
          }

...

Future<FirebaseUser> linkWithEmailPassword(String email, String password) async {
    AuthCredential credential = EmailAuthProvider.getCredential(email: email, password: password);
    AuthResult auth = await currentUser.linkWithCredential(credential);
    if (auth.user != null) {
      print("Linking accounds succeeded");
      return auth.user;
    } else {
      // TODO: Linking accounts fails if the credential was already linked to another user accounts
      // In this case we must merge accounts manually
      print("** /n/n LINKING ANONYMOUS ACCOUNT FAILED /n/n **");
      return null;
    }
  }

I get the exception on the line AuthResult auth = await currentUser.linkWithCredential(credential);, the if-else clause right after that never runs, always fails on linkWithCredential.

@iapicca I am happy to provide more context or code samples if it will help!

@jahngergely Yeah, I have been able to login anonymously without any issues across all the versions of the firebase_auth library I've used. My problem is linking the anonymous account with a email/password credential. I just tried the 0.15.0+1 version and I got the same error.

also, @iapicca I read on someone's StackOverflow response that in order to link email/password credentials to another user, you have to allow for multiple accounts per email. Is that true? Either way, I turned that option on but that didn't fix the issue for me.
Screen Shot 2019-12-09 at 9 41 04 AM

Fix will be landing soon (see #1588).

Fix landed. Please run pub upgrade and verify that this fixes your issue!

@hterkelsen I can confirm this works - had the same issue, ran flutter pub upgrade tonight and it's working like a charm.

oh whoops I meant to respond to the update
@hterkelsen same as the previous comment, running flutter pub upgrade solved the issue for me. Things are working great!

thanks for the lightning fast response to this one! 馃帀

Was this page helpful?
0 / 5 - 0 ratings