An exception was throw by _MapStream<FirebaseUser, User> listened by StreamProvider<User>, but no `catchError` was provided

Issue

<— UPDATE —>

FOUND THE SOLUTION. CHECK ANSWER BELOW

<— UPDATE —>

Any ideas why this is happening, what causes the bug, and how do I fix it?

I was following TheNetNinja’s tutorial on YouTube and I’ve seen people had a similar problem, but not quite the same.

An exception is thrown when the app is closed suddenly (using the stop button in Android Studio) without logging out and then restarted, only when using e-mail and pass login. For Google login, it seems to work fine. Also, this doesn’t happen if I manually create a new user in Firebase Console and login for the first time.

THE EXCEPTION:

════════ Exception caught by provider ══════════════════════════════════════════════════════════════
The following assertion was thrown:
An exception was throw by _MapStream<FirebaseUser, User> listened by

StreamProvider<User>, but no `catchError` was provided.

Exception:
RangeError (index): Invalid value: Only valid value is 0: 1

════════════════════════════════════════════════════════════════════════════════════════════════════

I’m using firebase_auth: ^0.16.0 in my pubspec.yaml and I’m thinking it might have something to do with the version.

When I log in, I get this output

I/BiChannelGoogleApi(17821): [FirebaseAuth: ] getGoogleApiForMethod() returned Gms: com.google.firebase.auth.api.internal.zzaq@cd1fa83
D/FirebaseAuth(17821): Notifying id token listeners about user ( 1EMwk8483hQWnSQwJeQYm9AcpiD2 ).

which looks like the account gets verified and logged in, but then the screens don’t change, so I guess it gets stuck somewhere in the verification process.

And the weird thing is, if I log in normally with the exception and restart the app, it works just fine. If I keep restarting it, it works just fine, but if I suddenly stop it, I get the exception again.

This is my authentication code

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:common_ui_module/Utils.dart';
import 'package:user_module/Role.dart';
import 'package:user_module/User.dart';
import 'package:localization_module/AppLocalizations.dart';

class AuthService {
  final FirebaseAuth _auth = FirebaseAuth.instance;

    return user != null
        ? User(uid: user.uid)
        : null;
  }

  Stream<User> get user {
    // map FireBaseUsers to User objects
    return _auth.onAuthStateChanged.map(_userFromFireBaseUser);
  }


// sign in with email and pass
  Future<User> signInWithEmailAndPassword(String email, String pass) async {
    try {
      AuthResult result =
          await _auth.signInWithEmailAndPassword(email: email, password: pass);
      FirebaseUser user = result.user;
      assert(await user.getIdToken() != null);
      print(
          "Signed in: ${user.email} , pass: $pass, phone: ${user.phoneNumber}");

      /// return the mapped user
      return _userFromFireBaseUser(user);
    } catch (e) {
      print(e.toString());
      return null;
    }
  }


// sign out
  Future signOut() async {
    try {
      return await _auth.signOut();
    } catch (e) {
      print(e.toString());
      return null;
    }
  }
}

This is the Wrapper that switches between Login and main screen

class Wrapper extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final User user = Provider.of<User>(context);

    if (user != null) {
      return RestaurantOrdersScreen();
    } else {
      return LoginScreen();
    }
  }
}

And I’ve wrapped the main application in a MultiProvider:

Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        /// PROVIDER FOR AUTHENTICATION
        StreamProvider<User>.value(
          value: AuthService().user,
        ),

       //...
       // some other providers
      ],
      child: MaterialApp(
        home: SplashScreen(),
      ),
    );
  }

Solution

FINALLY FOUND A FIX FOR IT!

For me, it was this split when I was trying to manipulate the displayName. That’s why I was getting the index out of range error.

List<String> name = ["", ""];
    if (user != null && user.displayName != null) {
      name = user.displayName.split(" ");
    }

    return user != null
        ? User(
            id: 0,
            token: user.uid,
            firstName: name[0],
            lastName: name[1],
...

So, if you get this kind of error, carefully check your User attributes manipulation when trying to convert FirebaseUser into your own custom User object.

Answered By – Mad World

Answer Checked By – Candace Johnson (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *