improve error types and messages #4744

Closed
staticfloat opened this Issue Nov 6, 2013 · 14 comments

Projects

None yet

7 participants

@staticfloat
Member

I think it would really be to our benefit to clean up how errors are printed in Julia. Examples:

julia> complex(1,2) > 0
ERROR: no method isless(Int64,Complex{Int64})
 in > at operators.jl:19

This doesn't tell me anything about the type of the error (in case I wanted to catch it, for instance), but does tell me something mildly helpful; namely that I attempted to call a function that doesn't exist.

julia> a = []
0-element Array{None,1}

julia> a[-1]
ERROR: BoundsError()
 in getindex at array.jl:277

julia> iround(Inf)
ERROR: InexactError()
 in iround at float.jl:79

On the other hand, these tell me the type of the error but don't tell me much beyond that. It'd be nice to have some kind of human-readable string to make this a little friendlier.

julia> parse("9223372036854775808")
ERROR: ParseError("invalid numeric constant 9223372036854775808")
 in parse at string.jl:1199
 in parse at string.jl:1212

This is the nicest so far because everything I'm looking for is there (type for catching, description, etc....), however it's not exactly printed in the nicest way; it's printed out in faux-"AST literal" fashion. I don't know if there's a much better way to print exceptions out, but I'm willing to think about it if others agree.

I'd like to propose that when exceptions in Base throw and are printed to the console, that they are represented with their type, a human-readable description of the error (simple exceptions such as BoundsError() could have a default boilerplate so as to not have developers copy-pasting the same string everywhere)

@StefanKarpinski
Member

+10^6

@staticfloat
Member

After writing #4745, I have come to see ErrorException as a prime suspect in these crimes against usability. Hyperbole aside, it would be a great cleanup project for someone to find all the instances of ErrorException and try to map them to more specific error types. I'm not sure we want to go down the road of CausalityViolationException etc..., but for instance, a lot of our IO code throws ErrorException for IO-specific things. Even just a generic IOError would be better than ErrorException.

This seems like a good project for someone looking for an excuse to get some exposure to base/, but without having to muck around with anything too critical/involved, hence the "up for grabs" tag.

@ivarne
Contributor
ivarne commented Nov 7, 2013

I think this issue is to wide, so we need to narrow it down.

  1. ErrorException is used too much. My feeling is that if an ErrorException needs to be caught for other purposes than testing and error reporting, a more specific exception should be used.
  2. Change the printing of the no method $method error to that of a regular exception.
  3. Add msg fields to most/all exceptions so that users can be helped better when Julia throws errors because the user does not know Julia well enough.

@JeffBezanson said something about the efficiency of adding messages to exceptions in #2144 (comment), but somehow the string allocation and processing should be possible to defer to after we know there is an error. Another approach is to specialize the showerror method for the different exceptions and search the stack trace to give a well informed error like in #4249, but it is not very intuitive for new users to find out what is going on.

@JeffBezanson
Member

We should

  • look through uses of error to see what new exception types might be needed. probably not many.
  • change most uses to more appropriate types, which includes many cases in the code generator
  • print errors as ErrorType: message. I never really liked the ERROR prefix.
@JeffBezanson
Member

We also have to decide what to do with UVError.

@staticfloat
Member

A relatively small task that would be helpful in this regard:

  • DomainError should probably have a msg::String field, so that it can contain a message to be printed out when it's thrown. See #4830 (comment) for a practical consequence of the lack of this field.
@timholy
Member
timholy commented Nov 25, 2013

There were several points made in https://groups.google.com/d/msg/julia-dev/NDtV8aa8XLk/ZSysXqOvun0J that may be worth considering.

@StefanKarpinski
Member

Another major improvement would be to fully qualify names. I just encountered ("in the wild") a case where there was a module defining a Timer type and since Base also exports a Timer type, things were failing in a way that was non-obvious because the names were not qualified in error messages. If they had been printed as Base.Timer and MyModule.Timer then it would have been immediately obvious what was going on. The tricky part here is that you don't want to have annoyingly long names in all error messages, so knowing when to qualify and when not to qualify might be hard.

@jiahao jiahao added a commit that referenced this issue Dec 9, 2013
@jiahao jiahao At build time, check for correct size of BlasInt.
Returns helpful error message as discussed in #5050, #4744
c26206a
@hayd
Member
hayd commented Nov 1, 2014

Should we have every Base error have a msg attribute (not sure if it's possible to "enforce" this - sounds like a trait!) to have a default for each error, or (in some cases maybe :s ) make a message required ?

Happy to put something together here, if this is desired, I have the first part already (print DomainError rather than ERROR):

DomainError: default error message (about what a domain error is ??)
DomainError: message passed about this specific domain error
...more stuff (as is currently printed)

IMO this is better/more flexible than:

ERROR: DomainError()
@timholy
Member
timholy commented Nov 1, 2014

While it sounds good in principle, depending on implementation there might be some unintended side effects. See #6698 (comment).

See also #8784

@ivarne
Contributor
ivarne commented Nov 1, 2014

As we have a specific method to print DomainError(), it is very easy to print a FAQ style answer to "How is DomainErrors used in Julia?" every time the exception is printed.

The question is whether we want to print a short doc, or refer to something like help(DomainError) (which currently doesn't work by the way). Backtraces are usually cluttered enough and a paragraph of documentation doesn't make it cleaner.

@hayd
Member
hayd commented Nov 1, 2014

By default (in python) if you do ValueError() is equivalent to ValueError(""), i.e. it prints:

ValueError:

We could do the same (so as to cause less clutter).

@hayd
Member
hayd commented Nov 1, 2014

Ah I hadn't seen the performance issue (thanks for linking to that). I still think that:

BoundsError:

would be a better exception (even with an empty message, which is currently added on a per-exception basis with showerror) than:

ERROR: BoundsError()
@jakebolewski
Member

The exception types thrown in Base has been improved for many methods. It would be more helpful to open issues on individual errors that need improvement so I'm closing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment