While learning flutter/dart, I came across this issue:
I'm calling this method in a FutureBuilder somewhere in my app:
Future<DatabaseUser> getOrCreateUser({required String email}) async {
try {
final user = await getUser(email: email);
return user;
} on UserDoesNotExistsException {
final createdUser = await createUser(email: email);
return createdUser;
} catch (e) {
print(e);
rethrow;
}
}
Once called for the first time, the "getUser" throws a UserDoesNotExistsException, which is correct, so it should go to the line:
} on UserDoesNotExistsException {
This is the issue, it always goes straight to the line:
} catch (e) {
If I print (e), I have UserDoesNotExistsException (see screenshot)
Let me know if you need more context here, what could make sense in that situation? Why is the Exception not caught by the right bloc?
Any help would be really appreciated
PS: I'm following this 37h+ video tutorial: https://www.youtube.com/watch?v=VPvVD8t02U8&t=28781s I'm at 21:36:00
Thanks
Screenshot Debugger
Issue solved.
As julemand101 suggested, a print(e.runtimeType) exposed the type of e as Type and not Exception.
The reason was a missing () when the Exception is thrown:
if (result.isEmpty) {
throw UserDoesNotExistsException;
} else {
return DatabaseUser.fromRow(result.first);
}
instead of
if (result.isEmpty) {
throw UserDoesNotExistsException();
} else {
return DatabaseUser.fromRow(result.first);
}
Visual Studio Code doesn't give any warning about this by default, but as julemand101 suggested in the comments, the analyzer can be configured to give a warning when you don't throw an Error or Exception:
https://dart-lang.github.io/linter/lints/only_throw_errors.html
Related
I keep getting the following error message in VS Code when I try to run this dart package:
**The method 'errorMessage' isn't defined for the type 'Object'.
Try correcting the name to the name of an existing method, or defining a method named 'errorMessage'.
**
Anytime I write this code:
void main(){
try {
depositMoney(-200);
} catch (e) {
print(e.errorMessage());
}
}
class DepositException implements Exception {
String errorMessage() {
print("You cannot enter amount less than 0! ");
return errorMessage();
}
}
void depositMoney(int amount) {
if (amount < 0) {
throw new DepositException();
}
}
What should I do??
Change your try catch block like this,
try {
depositMoney(-200);
} on DepositException catch (e) {
print(e.errorMessage());
}
This is because, DepositException is a custom exception class.
If you want catch all errors, you can do it this way,
try {
depositMoney(-200);
} catch (e) {
if(e is DepositException){
print(e.errorMessage());
}else{
print(e);
}
}
I want check if Api Url Statuscode is 200 , everything is ok untill in else statement .
I Got this error
Exception has occurred.
_Exception (Exception: Failed Load Data)
It's My Code Api
Future<List<Mosque>> getMahasiswaById(String id) async {
var baseURL=Urls.BASE_API_URL;
var apiRespon = await http.get('$baseURL/mahasiswa/get/id/$id');
if(apiRespon.statusCode == 200) {
final apiResponJson = json.decode(apiRespon.body);
print(apiResponJson);
return (apiResponJson['data'] as List).map((p)=>Mosque.fromJson(p)).toList();
} else {
throw Exception('Failed Load Data');
}
}
How can i fix this ? Thanks
always use try and catch with http requests it'll help you to identify the source of the exception , you can do something like that :
Future<List<Mosque>> getMahasiswaById(String id) async{
var baseURL=Urls.BASE_API_URL;
try{
var apiRespon = await http.get('$baseURL/mahasiswa/get/id/$id');
if(apiRespon.statusCode == 200){
final apiResponJson = json.decode(apiRespon.body);
print(apiResponJson);
return (apiResponJson['data'] as List).map((p)=>Mosque.fromJson(p)).toList();
}
else {
print(apiReson.statusCode.toString());
throw Exception('Failed load data with status code ${apiReson.statusCode}');
}
catch(e){
print (e);
throw e;}
}
most of the time the exceptions come from bad internet connection , issue in the back end or lost in the internet connection ,when you use the above code it'll print out the type of the exception so you can identify the root of the error.
I hope that can help
I'm using WebSocket variable in my MyWebSocket class. For listen i give a callback function as parameter.
If this callback function throws an exception in calling class MyChat, then i can not catch that exception anywhere.
My simplified code is:
class MyWebSocket {
WebSocket _ws;
...
// initialized in controller: _ws = WebSocket.connect(_some_url_);
// everything works (connect, listen)
...
void listen({void Function(dynamic) myOnListen}) {
try {
_ws.listen(myOnListen)
.onError((e) => print("MyWebSocket in MyChat.onError: $e"));
} catch (e) {
print("Catched in MyWebSocket: $e");
}
}
}
class MyChat {
MyWebSocket _chatWs = MyWebSocket();
...
void initWS() {
try {
_chatWs.listen(myOnListen: processMsg);
} catch (e) {
print("Catched in MyChat: $e");
}
}
void processMsg(dynamic msg) {
if(_some_stuff_like_invalid_msg_or_not_logged_in_...)
throw Exception("There is my Exception");
}
}
I have built try-catch in every possible place to catch exceptions - no success, i got only unhandled exception:
E/flutter: [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Exception: There is my Exception
E/flutter: #0 MyChat.processMsg
Beware that you cannot use the passed listener as a key for later removal. For that you can pass the new listener created in MyWebSocket class when listen() is called, then use this key to remove the listener.
class MyWebSocket {
WebSocket _ws;
void listen({void Function(dynamic) myOnListen, void Function(Error) onError}) {
try {
_ws.listen((){
try {
myOnListen({"label": "DATA"});
} catch (e) {
if(onError is Function)
onError(e)
}
})
.onError(onError);
} catch (e) {
print("Catched in MyWebSocket: $e");
}
}
}
class MyChat {
MyWebSocket _chatWs = MyWebSocket();
void initWS() {
try {
_chatWs.listen(myOnListen: processMsg, onError: (Error error){
print("ERROR: "+error.toString());
});
} catch (e) {
print("Catched in MyChat: $e");
}
}
void processMsg(dynamic msg) {
if(_some_stuff_like_invalid_msg_or_not_logged_in_...)
throw Exception("There is my Exception");
}
}
You need to handle it inside your processMsg
If you analyze carefully the execution of your code the _ws.listent register a listener for when you receive a message and that will happen in the FUTURE, but you don't get an error WHILE you are REGISTERING your listener that's why that doesn't work the way you expect.
processMsg will do something in the future, it will throw an error and it's at the end of the pipeline.
You are simulating an exception and nothing is handling it, it happens in a different stack frame, in the future.
The void listen({void Function(dynamic) myOnListen}) function execution is long gone when you receive and you precessMsg.
Alternatively you could do:
Function tryCatchHOF(Function cb) {
decorated(dynamic param) {
try {
cb(param);
} catch (e) {
print("$e");
}
}
;
return decorated;
}
void processMsg(dynamic msg) {
if (true) throw Exception("There is my Exception");
}
var processMsgWithTryCatch = tryCatchHOF(processMsg);
processMsgWithTryCatch('');
and then pass processMsgWithTryCatch down to your listener if you don't want to handle inside processMsg
I hope that make sense
I have a Azure Mobile Apps Xamarin.Forms PCL client and have Offline Sync enabled. I tried to Pull data from my backend and afterwards query data from the offline storage with a Where clause. That throws the following exception and I don't know why.
Sync error: 'fahrerinfo.Imei.Equals("02032032030232")' is not supported in a 'Where' Mobile Services query expression.
public async Task SyncAsync()
{
ReadOnlyCollection<MobileServiceTableOperationError> syncErrors = null;
try
{
await OfflineSyncStoreManager.Instance.TruckFahrerTable.PullAsync("allTruckFahrerItems",
OfflineSyncStoreManager.Instance.TruckFahrerTable.CreateQuery());
Debug.WriteLine("SyncAsync: PUSH/PULL completed.");
}
catch (MobileServicePushFailedException e)
{
Debug.WriteLine("SyncAsync: PUSH failed.");
Debug.WriteLine(e.Message);
}
catch (Exception e)
{
Debug.WriteLine("SyncAsync: PUSH/PULL failed.");
Debug.WriteLine(e.Message);
//Debugger.Break();
}
}
public async Task<ObservableCollection<TruckFahrer>> GetTruckFaherAsync(bool syncItems)
{
try
{
if (syncItems)
{
await OfflineSyncStoreManager.Instance.SyncAsync().ConfigureAwait(false);
}
var deviceInfo = DependencyService.Get<IDeviceInfo>().GetPhoneInfo();
var imeiString = deviceInfo[trucker_rolsped.PhoneInfo.PhoneInfo.ImeiKey];
var imei = imeiString.Equals("000000000000000") ? deviceInfo[trucker_rolsped.PhoneInfo.PhoneInfo.IdKey] : imeiString;
IEnumerable<TruckFahrer> items =
await OfflineSyncStoreManager.Instance.TruckFahrerTable
//.Where(fahrerinfo => fahrerinfo.Imei.Equals(imei)) TODO: Why does that throw an exception???
.ToEnumerableAsync();
// TODO: Because above does not work
items = items.Where(fahrer => fahrer.Imei.Equals(imei));
return new ObservableCollection<TruckFahrer>(items);
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine(#"Invalid sync operation: {0}", msioe.Message);
Debugger.Break();
}
catch (Exception e)
{
Debug.WriteLine(#"Sync error: {0}", e.Message);
Debugger.Break();
}
return null;
}
Thanks for any hint,
Eric
Are you a Java developer too? I'm and had this issue because in Java we need to compare strings with String#equals method, haha.
For some reason MobileServices doesn't allow us to use Equals in this situation.
To fix your problem, use == instead. As you can see here C# difference between == and Equals() both have the same effect in this case.
Where(fahrerinfo => fahrerinfo.Imei == imei)
I'am trying to write some messages to Windows Event log.
The (security) exception will be thrown when calling function "SourceExists()".
private bool CheckIfEventLogSourceExits()
{
try
{
if (!EventLog.SourceExists(this.BaseEventLog))
{
return false;
}
return true;
}
catch (System.Security.SecurityException)
{
return false;
}
}
All answers to this question are explaining how you can MANUALLY resolve issue.
Like here: Stackoverflow Thread. Solution would be changing some registry keys
But you can't expect that everyone who consumes your application is aware of these changes.
So my question is, how can we solve this issue programmatically?
Below my code:
try
{
string sLog = "Application";
if (CheckIfEventLogSourceExits())
{
EventLog.CreateEventSource(this.BaseEventLog, sLog);
}
EventLog.WriteEntry(this.BaseEventLog, message, eventLogEntryType);
}
catch (Exception ex)
{
ex.Source = "WriteToEventLog";
throw ex;
}
I know it's too late for this posting, but the answer, I found from similar experience, is that the service you're running under doesn't have administrative rights to the machine and, thus, can't write to the logs.
It's easy enough to figure out if an app is being run under admin rights. You can add something like this to your code with a message box advising the user to run "admin".
private void GetServicePermissionLevel()
{
bool bAdmin = false;
try {
SecurityIdentifier sidAdmin = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
AppDomain myDomain = Thread.GetDomain();
myDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsPrincipal myPrincipal = (WindowsPrincipal)Thread.CurrentPrincipal;
if (myPrincipal.IsInRole(sidAdmin)) {
bAdmin = true;
} else {
bAdmin = false;
}
} catch (Exception ex) {
throw new Exception("Error in GetServicePermissionlevel(): " + ex.Message + " - " + ex.StackTrace);
} finally {
_ServiceRunAsAdmin = bAdmin;
}
}