julia> try
run(`false`)
catch err
dump(err)
end
ErrorException
msg: ASCIIString "failed process: Process(`false`, ProcessExited(1)) [1]"
julia> try
run(`foobar`)
catch err
dump(err)
end
UVError
prefix: ASCIIString "could not spawn `foobar`"
code: Int32 -2
I feel like UVError isn't something that should be escaping the Julia internals. For one thing, I doubt anyone not involved with Julia development knows or wants to know what the UV refers to. Having different exception types thrown from the same method (from the users perspective) feels odd to me, although I think thats a much more debatable point.
It bit me recently (I had code like println(fp, err.msg), which threw an error in the error handler...) and I just saw https://github.com/JuliaLang/julia/pull/7822 which made me think of it again.
Wholeheartedly agree.
We had a long talk about this today. I think our general consensus was that we definitely want granularity of errors, (e.g. not just reporting everything as a generic ErrorException even with a helpful string) correctness of naming (calling things UVError is a little too implementation-specific, but then again most of our I/O subsystem is based on libuv) so as not to confused users, and consistency across Base.
The best short-term proposal (e.g. something within scope for 0.4) I can come up with is the following: Create categories of errors that are small enough to be meaningful (e.g. IOError), and present those to the user with libuv error codes embedded, and friendly string messages given at the time of raising the exception. This has the following benefits:
I've been complaining about UVError for some time:
https://github.com/JuliaLang/julia/issues/6825#issuecomment-42912316
https://github.com/JuliaLang/julia/issues/1924#issuecomment-14276785
See also #4744
Also, an exception type should describe a problem, not which library threw it.
I think this is still relevant (the original example still works). UVError is not exported from Base, so is it correct that its OK to put this off past 1.0?
Agree this should be replaced with SystemError, IOError, etc.
Shouldn't this be on the 0.7 milestone rather than 1.0?
Yes I think this could be on the 0.7 milestone, but it's fairly minor since code probably doesn't reference UVError too often.
In #15879 a subset of UVError was replaced by DNSError. A quick scan of the possible UV_ error codes suggests that there is scope to continue this pattern and split out more specific error types in future (IOPermissionError?, IOBusyError?, HostUnreacableError?).
However, I'm concerned that baking IOError into 1.0 with its current meaning would preclude splitting out more fine-grained error types.
e.g if the code below was written for Julia 1.0, it would stop working if IOPermissionError was later added as a fine-grained error type for UV_EACCES.
catch e
if e isa IOError && e.code == UV_EACCES
bar()
else
rethrow(e)
end
end
It might be better for IOError to be an abstract type so that a future IOPermissionError could be <: IOError. Then code like the following would continue to work as fine-grained error types are added:
catch e
if e isa AbstractIOError && errorcode(e) == UV_EACCES
bar()
else
rethrow(e)
end
end
Ok so should we just add AbstractIOError above IOError (and EOFError and DNSError)?
Technically making IOError abstract in the future is not a breaking change. Dispatch on it and fields that use it as a type would continue to work as expected. Only code that was written to the new subtypes would see any difference and that's not breaking.
Then perhaps the IOError.code field should be renamed to uvcode (syscode? internalcode?). Otherwise future IOError subtypes can't use the field name code.
e.g. if HTTPError <: IOError then .code would be 404 not a UV_ code.
The code field is implementation-defined anyway; it's pretty hard to commit to a meaning for all of its possible values. HTTPError would specify that .code is an HTTP error code, but IOError says the code is implementation-defined and you don't really know what it is.
Most helpful comment
I think this is still relevant (the original example still works). UVError is not exported from Base, so is it correct that its OK to put this off past 1.0?