following code as docs mention:
try {
breedMoreLlamas1();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e');
} catch (e) {
// No specified type, handles all
print('Something really unknown: $e');
}
void breedMoreLlamas1() {
print('buyMoreLlamas_1');
throw Exception;
}
I get buyMoreLlamas_1 and the message Something really unknown: Exception
Shouldn't be : Unknown exception: Exception
Any suggestion?
Related
If I have nested async* streams, exceptions do not appear to be catchable, which is counterintuitive.
An example:
void main() {
getString().listen(print);
}
Stream<String> getString() async* {
try {
yield* asyncStarError();
yield await asyncError();
} catch (err) {
yield 'Crash';
}
}
Stream<String> asyncStarError() async* {
throw Exception('A Stream error happened');
}
Future<String> asyncError() async {
throw Exception('A Future error happened');
}
This outputs:
Uncaught Error: Exception: A Stream error happened
Crash
So the exception thrown by asyncStarError is not caught, while the Future is caught as expected. Can anyone explain why?
You can observe the behaviour in dartpad: https://dartpad.dartlang.org
The yield* forwards all events from the stream it yields, including errors.
So, asyncStarError() produces a stream with an error event, and yield* forwards that error to the stream returned by getString, and then the getString.listen(print); does not add a handler so the error becomes uncaught.
(I'm guessing you're running this in a browser since that uncaught error doesn't crash the program.)
After that, the yield await asyncError() never yield anything. The await asyncError() itself throws, before reaching the yield, and that error is then caught by the catch which yields crash.
If you want to catch the errors of a stream, you need to actually look at the events, not just use yield* to forward them all blindly, including error events.
For example:
await for (var _ in asyncStarError()) {
// Wohoo, event!
}
would make the error from the asyncStarError stream an error at the loop. It would then be caught and you'd print "Crash".
TL;DR: The yield* operation forwards error events, it doesn't raise them locally.
Since yield * forwards them like #lrn said, you can catch them in main just fine. Or wherever you are consuming them.
void main() {
getString().listen(print).onError((e) => print('error caught: $e'));
}
Stream<String> getString() async* {
try {
yield* asyncStarError();
yield await asyncError();
} catch (err) {
yield 'Crash';
}
}
Stream<String> asyncStarError() async* {
throw Exception('A Stream error happened');
}
Future<String> asyncError() async {
throw Exception('A Future error happened');
}
this prints:
error caught: Exception: A Stream error happened
Crash
The difference is that async generator (async*) exceptions cannot be caught by surrounding it with try/catch.
Instead, you should use the callback handleError to achieve the behaviour you are looking for.
To go further, you may be interested in using runZonedGuarded.
In Electron if I throw an error anywhere on the backend it goes to a custom window. Trying to find a way to catch that to push to a custom area in my app I've found that I can detect the process with process.on('uncaughtException'). However I'm stuck trying to run a sender to send either the error or the report. What I've tried:
ipcMain.on('main', async (e, data) => {
try {
await someModule(data)
process.on('uncaughtException', err => e.sender.send('error', err.message))
return e.sender.send('audit', 'No issues found')
} catch (err) {
console.log(err)
}
})
module.js:
module.export = data => {
throw Error('this is a test')
}
In the above I'm sending both get both errorandaudit` to renderer. I've researched for a way to pass 'uncaughtException' to a ternary but I'm not able to find any docs on how to condition for 'uncaughtException' but I did try:
process.on('uncaughtException', err => {
if (err) return e.sender.send('error', err.message)
return e.sender.send('audit', 'test complete')
})
and the above only works if an error is present, research:
Catch all uncaughtException for Node js app
Nodejs uncaught exception handling
Node.js Uncaught Exception - Passing more details
In Electron how can I intercept the error to pass it to renderer from main without throwing the default error window?
If you use ipcMain.handle you will be able to handle errors in the renderer process like this
// Main process
ipcMain.handle('my-invokable-ipc', async (event, data) => {
await someModule(data)
return 'No issues found'
})
// Renderer process
async () => {
try {
const result = await ipcRenderer.invoke('my-invokable-ipc', data)
console.log(result) // 'No issues found' if someModule did not throw an error
} catch (err) {
// you can handle someModule errors here
}
}
Update: An issue with this approach is that the error emitted to the renderer process is serialized and it gets printed even though it's handled with a try/catch.
To fix this, you can also handle the errors in the main process
// Main process
ipcMain.handle('my-invokable-ipc', async (event, data) => {
try {
await someModule(data)
return 'No issues found'
} catch (err) {
// handle someModule errors and notify renderer process
// return err.message or any other way you see fit
}
})
// Renderer process
async () => {
const result = await ipcRenderer.invoke('my-invokable-ipc', data)
console.log(result) // 'No issues found' if someModule did not throw an error
}
I have written a simple command line tool in dart that watches changes in a directory if a directory does not exits I get FileSystemsException.
I have tried to handle it using try and catch clause. When the exception occurs the code in catch clause is not executed
try {
watcher.events.listen((event) {
if (event.type == ChangeType.ADD) {
print("THE FILE WAS ADDED");
print(event.path);
} else if (event.type == ChangeType.MODIFY) {
print("THE FILE WAS MODIFIED");
print(event.path);
} else {
print("THE FILE WAS REMOVED");
print(event.path);
}
});
} on FileSystemException {
print("Exception Occurs");
}
I expect the console to print "Exception Occurs"
There are two possibilities:
The exception is happening outside this block (maybe where the watcher is constructed?)
The exception is an unhandled async exception. This might be coming from either the Stream or it might be getting fired from some other Future, like perhaps the ready Future.
You can add handlers for the async exceptions like this:
try {
// If this is in an `async` method, use `await` within the try block
await watcher.ready;
// Otherwise add a error handler on the Future
watcher.ready.catchError((e) {
print('Exception in the ready Future');
});
watcher.events.listen((event) {
...
}, onError: (e) {
print('Exception in the Stream');
});
} on FileSystemException {
print("Exception Occurs");
}
My guess would be it's an error surfaced through the ready Future.
context.setLineDash() works in Chrome, but in FireFox 18.0.1 results in
TypeError: this.setLineDash is not a function
deep in the bootstrap.dart.js file.
Even if I use this function
void setLineDashCatch(var ctx,var param) {
try {
ctx.setLineDash(param);
} on Exception catch (e) {
log('SetLineDash exception');
}
}
The exception is not caught, and the method is aborted.
What is the best way to avoid the method being aborted?
You don't get the log because it is not an Exception that is thrown. It is rather a NoSuchMethodError. The following code should work :
void setLineDashCatch(var ctx,var param) {
try {
ctx.setLineDash(param);
} on NoSuchMethodError catch (e) {
print('SetLineDash exception');
}
}
When I try to catch an Exception in a controller method I could not catch SocketException. The controller action looks like:
def updateDeviceStartV1() {
try {
...
response.status = 200;
response.setContentType("application/octet-stream")
response.outputStream << responseService.encryptedResponse // byte[]
}
catch(Exception e) {
log.error "Server faced unexpected exception", e
response.status = 500;
...
}
The SocketException is thrown by line "response.outputStream << responseService.encryptedResponse" because the client unexpectedly close the connection. Nevertheless, this exception is not catched and the console receives standard exception display...
Am I doing something wrong?
I think that if the method where the exception is raised doesn't throw the exception explicitly (with a throws in the signature), it will be thrown as an UndeclaredThrowableException. Then the type in your catch just doesn't match it. Try catching SocketException instead. Or if you can just catch them all using catch(all).
Oh, take a look at this.