how to get Firebase Firestore exception code on Flutter? - firebase

from the documentation in here it seems that Firestore have some error codes. how to catch that in Flutter so I can localize the error message
I have tried to use the code below
Future<User?> getUser({required String userID}) async {
try {
final documentSnapshot = await _db.collection(path).doc(userID).get();
if (documentSnapshot.exists) {
return User.fromFirestore(documentSnapshot.data()!);
} else {
return null;
}
} on FirebaseFirestoreException (error) {
print(error.code);
// I hope I can get the error.code in here
}
}
but I have error

_db.collection(path).doc(userID).get()
.then((e){
User user = User.fromFirestore(e.data()!);
}).catchError((err)=> print(err.message));

Related

Unhandled Exception: FormatException: Unexpected character

I couldn't transform my fetched the data,
But no errors showing, I have added a print statement to find error where it occurs
Future<void> fetchAndSetProduct() async {
final url =
Uri.https('shopda-83b00-default-rtdb.firebaseio.com', '/products');
try {
print("karan oneonofne ");
final response = await http.get(url);
final extractData = json.decode(response.body) as Map<String, dynamic>;
final List<Product> loadedProduct = [];
extractData.forEach((prodId, prodData) {
loadedProduct.add(Product(
id: prodId,
title: prodData['title'],
description: prodData['description'],
price: prodData['price'],
isFavourite: prodData['isFavourite'],
imageUrl: prodData['imageUrl']));
});
print(loadedProduct[1]);
_items = loadedProduct;
notifyListeners();
} catch (error) {
throw (error);
} finally {
print('object');
}
}
then I changed like this
Still, I couldn't get data.I think I couldn't change HTML to Jason
You're trying to fetch data from your Realtime Database by using the direct link.
This requires you to sign in and that is the HTML page it returns.
You should use the firebase_database package to fetch the data from the database.
You should update your fetchAndSetProduct method to this:
Future<void> fetchAndSetProduct() async {
try {
...
final DataSnapshot dataSnapshot = await FirebaseDatabase.instance.reference().child('products').once();
final extractData = json.decode(dataSnapshot.value) as Map<String, dynamic>;
...
} catch (error) {
...
} finally {
...
}
}
I found it Please change HTML file Json by simply
final url =
Uri.https('shopda-83b00-default-rtdb.firebaseio.com', '/products.json');

Flutter: PlatformException thrown by FireBase won't get caught

I have a function that is used to sign in to Firebase using firebase_auth, however, whenever an exception is thrown it isn't getting caught and still appears in the Android Studio console nor do the print statements in the catch block ever run.
How do I fix this?
signIn({String email, String password}) {
print('listened');
try {
FirebaseAuth.instance.signInWithEmailAndPassword(
email: email, password: password);
}
on PlatformException catch (signUpError) {
print(signUpError.code);
if (signUpError.code == 'ERROR_WEAK_PASSWORD') {
print('Weak Password');
}else if(signUpError.code=='ERROR_USER_NOT_FOUND'){
print('Invalid Username');
}
else{
print(signUpError.toString());
}
}
}
signInWithEmailAndPassword returns a Future<AuthResult> (it is asynchronous), therefore you need to use the catchError method to catch the error when calling an asynchronous method:
FirebaseAuth.instance.signInWithEmailAndPassword(email: email, password: password).then((result) {
print(result);
})
.catchError((error) {
print("Something went wrong: ${error.message}");
});
Check the following:
https://api.dart.dev/stable/2.3.0/dart-async/Future/catchError.html
https://medium.com/firebase-tips-tricks/how-to-use-firebase-authentication-in-flutter-50e8b81cb29f
The try catch blocks will work if the Firebase call is within an async function and the await statement is used when calling Firebase.
For example, in the following code an error getting the token will be trapped by the on PlatformException catch (... block but an error writing the token to FB RTDB won't be:
Future<void> _saveDeviceToken() async {
try {
final _currentUser = _firebaseAuth.currentUser;
final fcmToken = await _firebaseMessaging.getToken();
if (fcmToken != null) {
// Save the token to Firebase - NO AWAIT STATEMENT
globals.firebaseDatabase
.reference()
.child("pushTokens")
.child("${_currentUser.uid}")
.set({"token": fcmToken});
}
} on PlatformException catch (error, stackTrace) {
print("error: $error");
}
}
whereas adding the await statement, as in the following code, will trap errors in writing to FB RTDB as well:
Future<void> _saveDeviceToken() async {
try {
final _currentUser = _firebaseAuth.currentUser;
final fcmToken = await _firebaseMessaging.getToken();
if (fcmToken != null) {
// Save the token to Firebase - AWAIT STATEMENT ADDED
await globals.firebaseDatabase
.reference()
.child("pushTokens")
.child("${_currentUser.uid}")
.set({"token": fcmToken});
}
} on PlatformException catch (error, stackTrace) {
print("error: $error");
}
}
If you don't want to or can't use await then, as per Peter's answer, the solution is to use the catchError statement instead of try catch.

How to catch DatabaseError in Flutter Firebase App

I am learning Flutter and I want to catch the exception that should be thrown ( as security rule is correctly rejecting it) at the Flutter Application/device.
Below is the code
try {
FirebaseDatabase.instance.reference().once().then((DataSnapshot snapshot) {
try {
debugPrint(snapshot.toString());
}
on DatabaseError catch (eIn1) {
debugPrint(' onRoot ' + eIn1.toString());
}
});
}on DatabaseError catch (eOut1) {
debugPrint(' on1 ' + eOut1.toString());
}
try {
FirebaseDatabase.instance.reference().child("todo").once().then((DataSnapshot snapshot) {
try {
debugPrint(snapshot.toString());
}
on DatabaseError catch (eIn2) {
debugPrint(' onNode ' + eIn2.toString());
}
});
}on Exception catch (eOut2) {
debugPrint(' on2 ' + eOut2.toString());
}
But the Exception is never thrown or catch by the Android Studio, In logCat I can see the exception,
com.example.flutterlogindemo E/flutter:
[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception:
DatabaseError(-3, Permission denied, )
#0 Query.once (package:firebase_database/src/query.dart:84:41)
#1 _HomePageState.initState (package:flutter_login_demo/pages/home_page.dart:48:65)
but could not find a away to catch it in code and then act on the exception.
You can use the catchError to be able to catch the error:
FirebaseDatabase.instance.reference().child("todo").once().then((DataSnapshot snapshot) {
print(snapshot);
})
.catchError((error) {
print("Something went wrong: ${error.message}");
});
https://api.flutter.dev/flutter/package-async_async/DelegatingFuture/catchError.html
Repeating my answer to Flutter: PlatformException thrown by FireBase won't get caught here:
The try catch blocks will work if the Firebase call is within an async function and the await statement is used when calling Firebase.
For example, in the following code an error getting the token will be trapped by the on PlatformException catch (... block but an error writing the token to FB RTDB won't be:
Future<void> _saveDeviceToken() async {
try {
final _currentUser = _firebaseAuth.currentUser;
final fcmToken = await _firebaseMessaging.getToken();
if (fcmToken != null) {
// Save the token to Firebase - NO AWAIT STATEMENT
globals.firebaseDatabase
.reference()
.child("pushTokens")
.child("${_currentUser.uid}")
.set({"token": fcmToken});
}
} on PlatformException catch (error, stackTrace) {
print("error: $error");
}
}
whereas adding the await statement, as in the following code, will trap errors in writing to FB RTDB as well:
Future<void> _saveDeviceToken() async {
try {
final _currentUser = _firebaseAuth.currentUser;
final fcmToken = await _firebaseMessaging.getToken();
if (fcmToken != null) {
// Save the token to Firebase - AWAIT STATEMENT ADDED
await globals.firebaseDatabase
.reference()
.child("pushTokens")
.child("${_currentUser.uid}")
.set({"token": fcmToken});
}
} on PlatformException catch (error, stackTrace) {
print("error: $error");
}
}
If you don't want to or can't use await then, as per Peter's answer, the solution is to use the catchError statement instead of try catch.

Handling Firebase Insufficient Permissions Errors in Flutter

How can I handle insufficient permissions errors from firebase? I currently do this:
try {
DocumentSnapshot doc = await Firestore.instance.collection('SomeCollection').document('SomeDocument').get();
// Do something
} catch (error) {
print('Error: $error');
// Do something to show user
}
How ever I can't check for only Permission Errors. Sho how can I catch only insufficient permission errors?
Also when should I use .catchError(), I tried this:
DocumentSnapshot doc = await Firestore.instance.collection('Some Collection').document('Some Document').get().catchError((onError) {
// What to do here
});
I doens't seem to really catch a error, because the exception is still thrown
This is supposed to work
DocumentSnapshot doc = await Firestore.instance.collection('Some Collection').document('Some Document').get().catch((err)=>print(err));
You can recognize the permission error by the error code (which is 'permission-denied').
If it's a different error, you can throw it, or handle diffrently.
try {
DocumentSnapshot doc = await Firestore.instance.collection('SomeCollection').document('SomeDocument').get();
// Do something
} catch (error) {
if (error.code === 'permission-denied') {
// Do something to show user
}
else {
throw new Error(e); // Or do other things
}
}

How do I tell the difference between exceptions in flutter authenticating with Firebase?

I have Firebase a sign in for my app. I want to report exceptions to the user so he can correctly login. It is email and password sign in signInWithEmailAndPassword(_email, _password). Testing I can create two exceptions which are self explanatory
1/ Error: PlatformException(exception, There is no user record corresponding to this identifier. The user may have been deleted., null)
2/ Error: PlatformException(exception, The password is invalid or the user does not have a password., null)
I'm using a try catch block to catch the error. Here is my code:
void validateAndSubmit() async {
FocusScope.of(context).requestFocus(new FocusNode());
if (validateAndSave()) {
try {
var auth = AuthProvider.of(context).auth;
FirebaseUser user =
await auth.signInWithEmailAndPassword(_email, _password);
print('Signed in: ${user.uid}');
Navigator.pop(context);
widget.loginCallback(user);
} catch (e) {
print('Error: $e');
setState(() {
_showMessage=true;
});
}
}
}
I want to give a different message depending on the exception. But there doesn't seem to be any code associated with the exception.
You can catch different kind of exceptions, for each exceptions, you can check the code
void validateAndSubmit() async {
FocusScope.of(context).requestFocus(new FocusNode());
if (validateAndSave()) {
try {
var auth = AuthProvider.of(context).auth;
FirebaseUser user =
await auth.signInWithEmailAndPassword(_email, _password);
print('Signed in: ${user.uid}');
Navigator.pop(context);
widget.loginCallback(user);
} on FirebaseAuthInvalidUserException catch (e) {
print('FirebaseAuthInvalidUserException: $e');
if (e.code === 'ERROR_USER_NOT_FOUND') {
setState(() {
_showMessage=true;
});
} else {
// do something
}
}
} on FirebaseAuthInvalidCredentialsException catch (e) {
// do something InvalidCredentials
} catch (e) {
// do something else
}
}
You can check e.code.
Check out native firebase documentation. It has values like 'ERROR_USER_NOT_FOUND'

Resources