I've try to implement a function which take zlib bytes as argument using ZLIB of dart:io. And I want the function to catch the error caused by invalid zlib bytes.
However, I couldn't catch it. Because, it's class is a private class.
Here is an example code:
import 'dart:io';
main() {
try {
ZLIB.decode([1,2,3,4,5]);
} catch(e) {
print(e);
// InternalError: 'Filter error, bad data'
}
}
I think it can be catched with if (e.toString() == "InternalError: 'Filter error, bad data'") in the catch(e) block. But, toString() is not enough to identify a exception or a error.
What is the best way to handle this error exclude the above string comparison?
Actually you are catching the exception but sadly the exception doesn't provide more information about the cause.
There is nothing you can do about it beside filing a bug report/feature request for improved error messages.
Related
I need to collect only the first value from two emitted by flow.
I have a function that returns flow:
fun myFlow = flow {
try {
emit(localDataSource.fetchData())
} catch(e: Exception) {
// just skip this error
}
emit(remoteDataSource.fetchData(1000, 0))
}
In one special case I need only first emitted value, doesn't matter is it from local cache or remote source.
I tried this one:
fun getRandomFavoriteItem() = myFlow.first().filter { it.score > 7 }.randomOrNull()
But first() invocation always throws
java.lang.IllegalStateException: Flow exception transparency is violated:
Previous 'emit' call has thrown exception kotlinx.coroutines.flow.internal.AbortFlowException: Flow was aborted, no more elements needed, but then emission attempt of value.
What I've tried:
single() -
java.lang.IllegalArgumentException: Flow has more than one element
take(1).first() -
java.lang.IllegalStateException: Flow exception transparency is violated:
Previous 'emit' call has thrown exception kotlinx.coroutines.flow.internal.AbortFlowException: Flow was aborted, no more elements needed, but then emission attempt of value
Catch error but it doesn't stop here:
myFlow.catch { e ->
if (e !is IllegalArgumentException) {
throw e
}
}.first().filter { it.score > 7 }.randomOrNull()
My questions are:
What is the point of usage first() if it doesn't work in case of more than 1 emitted values? If I would know that my flow produces only one value I could just use any other terminal operator.
How to avoid those errors and how to collect only first value without adding repeated code?
This isn't an error in first(). It's an error in your flow. You are not permitted to swallow all exceptions in a Flow in the way you have.
Some varying approaches may differ in whether they detect that error, but what you must fix is how you "just skip" all exceptions. Consider catching only the specific exceptions you're concerned about, or at least making sure to catch and rethrow CancellationException or its subclasses.
Lous Wasserman already found the problem, here some more details.
As mentioned in the error message you're also catching the AbortFlowException.
java.lang.IllegalStateException: Flow exception transparency is
violated: Previous 'emit' call has thrown exception
kotlinx.coroutines.flow.internal.AbortFlowException: Flow was aborted,
no more elements needed, but then emission attempt of value.
You're bascically catching an exception which interferes with the way flows work. The problem is not about the first function.
Since AbortFlowException is internal you cannot access it, but you can access its superclass CancellationException. You need to modify your catch block like this:
try {
emit(localDataSource.fetchData())
} catch (e: Exception) {
if(e is CancellationException) {
throw e
}
}
Now first will work in the way you expect it to.
Edit:
A better solution would be to handle the exception within fetchData (you might return null in case one was thrown). This way you don't get in the way of the flow mechanics.
If that is not possible, you could create a wrapper function which takes care of the exception handling.
I'm trying to use the inline function use with a FileInputStream instead of the classic try/catch IOException so that
try {
val is = FileInputStream(file)
// file handling...
}
catch (e: IOException) {
e.printStackTrace()
}
becomes
FileInputStream(file).use { fis ->
// do stuff with file
}
My question is, why use the function use if it stills throws exception? Do I have to wrap use in a try/catch? This seems ridiculous.
From Kotlin documentation:
Executes the given block function on this resource and then closes it
down correctly whether an exception is thrown or not.
When you use an object that implements the Closeable interface, you need to call the close() method when you are done with it, so it releases any system resources associated with the object.
You need to be careful and close it even when an exception is thrown. In this kind of situation that is error prone, cause you might not know or forget to handle it properly, it is better to automate this pattern. That's exactly what the use function does.
Your try-catch does not close the resource so you are comparing apples to oranges. If you close the resource in finally block:
val is = FileInputStream(file)
try {
...
}
catch (e: IOException) {
...
}
finally {
is.close()
}
is definitely more verbose than use which handles closing the resource.
I found there is an old issue Sleuth/Zipkin tracing with #ControllerAdvice, but I meet the same problem with the latest version(spring-cloud-starter-zipkin:2.1.0.RELEASE), I debug it and find that the error is null, so zipkin just guess with statuscode. I have to throw the exception again to make zipkin notify the exception
error is null
zipkin result
ControllerAdvice
throw the exception again, it works
It makes perfect sense that it's null. That's because YOU control the way what happens with the caught exception. In your case, nothing, cause you swallow that exception.
If you want to do sth better, just add the error tag manually via the SpanCustomizer. That way you'll add the exception to the given span. It will then automatically get closed and reported to Zipkin (you can do sth else than ex.toString() of course.
#Slf4j
#RestControllerAdvice
#Order(Ordered.HIGHEST_PRECEDENCE)
public class ExceptionHanders {
private final SpanCustomizer customizer;
public ExceptionHanders(SpanCustomizer customizer) {
this.customizer = customizer;
}
#ExceptionHandler({RuntimeException.class})
#ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String handleRuntimeException(Exception ex) throws Exception {
this.customizer.tag("error", ex.toString());
return "testabcd";
}
}
I have a problem with the following code example:
Windows::Storage::StorageFolder^ location = Package::Current->InstalledLocation;
try
{
task<StorageFile^> GetFileTask(location->GetFileAsync(sn));
GetFileTask.then([=](StorageFile^ file)
{
try
{
task<IBuffer^> ReadFileTask(FileIO::ReadBufferAsync(file));
ReadFileTask.then([=](IBuffer^ readBuffer)
{
// process file contents here
});
}
catch(Platform::Exception^ ex)
{
// Handle error here
}
});
}
catch(Platform::Exception^ ex)
{
// Handle error here
}
When using a filename that doesn't exist the function throws an exception:
Unhandled exception at 0x0FFCC531 (msvcr110d.dll) in GameTest2.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
I've been searching the internet and this exception breaks only when connected to the debugger. I'm using VS 2012. I've turned off all the relevant 'break on exception' but it still causes the debugger to break and non of my handlers are getting a chance to handle the exception.
If the file is missing I would expect the GetFileAsync method to throw a 'File doesn't exist' exception. Not sure why it keeps throwing the 'Invalid parameter' exception.
This is starting to bother me and I just can't find any known solution to this issue. Anyone have any ideas?
I'm going to try and change the method to not use the task<> code. Instead I'll call the GetFileAsync using 'await'. However I believe 'await' will just cause the calling thread to wait until the GetFileAsync has finished, which kind of defeats the point of asynchronous loading.
I'm wondering if this is a common issue with exception handling when using tasks.
Update:
OK, I've now found the solution:
task<StorageFile^>( location->GetFileAsync(sn)).then([](StorageFile^ openedFile)
{
return FileIO::ReadBufferAsync(openedFile);
}).then([](IBuffer^ readBuffer)
{
// Process file
}).then([](task<void> t)
{
try
{
t.get();
}
catch(Platform::Exception^ e)
{
// Handle error
}
});
It seems there needs to be an extra 'then' condition added to the end of the chain to pick up the exception.
Excuses to my silly question, i wish to use a catch for specific exception, NSInvalidArgumentException, so, i have the next code in my OSX project:
#try
{
...
}
#catch(NSInvalidArgumentException* exception )
{
...
}
but xcode say me: "unknown type name 'NSInvalidArgumentException'", so i i was importing
import "Foundation/Foundation.h" or
import "Foundation/NSException.h"
but nothing happen, somebody known in what package or library is NSInvalidArgumentException? or which is my error? or is strictly necessary catch all exception using the superclass NSException? in the developer documentation do not show that so be it.
best regards.
NSInvalidArgumentException is not an exception type. It is a string that will be returned in the name property for an exception. So, you should catch your exception, and the name property does not match, you can re-#throw the exceptions you're not going to handle, e.g.:
#try {
// code that generates exception
}
#catch (NSException *exception) {
if ([exception.name isEqualToString:NSInvalidArgumentException])
{
// handle it
}
else
{
#throw;
}
}
See the Exception Programming Topics for more information.
I must confess that I share CodaFi's concern that this is not an appropriate use of exceptions. It's much better to program defensively, validate your parameters before you call Cocoa methods, and simply ensure that you don't generate exceptions in the first place. If you refer to the Dealing with Errors section of the Programming with Objective-C guide, exceptions are intended for "programmer errors" and they say:
You should not use a try-catch block in place of standard programming checks for Objective-C methods.
somebody known in what package or library is NSInvalidArgumentException?
It is declared in the Foundation Framework, in NSException.h. As CodaFi wrote in the comment, it is not a type, it is a string constant, declared as FOUNDATION_EXPORT NSString * const NSInvalidArgumentException;
So importing more headers won't fix your problem, because #catch(NSInvalidArgumentException* exception ) is like writing #catch(#"A string constant"* exception ), you have an object, where a type is expected.
Having said that, don't use exceptions for flow control. Have a look at the last part of this answer on SO