-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
DOC: add section about how to write good error messages #25292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
doc/devel/contributing.rst
Outdated
In cases like this it may be possible to get into a debugging and from reading | ||
the stack trace sort out right local variable to check is to start to sort out | ||
what went wrong. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure what is meant by "to get into a debugging", and not sure it's made better in context by saying "to get into a debugger", which was my first guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did mean "debugger".
doc/devel/contributing.rst
Outdated
While this does tell the user what variable and value Matplotlib rejected, it still | ||
does not tell them why. | ||
|
||
An example of a **best** error message :: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throwing your advice back to you, what about starting with the recommended best practice so that it won't get lost in skimming/fatigue? Then if it's still necessary, discuss unpack why the bad is bad - but honestly I'm not sure it's necessary given I think the paragraph under here does a good job of explaining why folks should do it this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with this - the first draft is pretty verbose....
doc/devel/contributing.rst
Outdated
Which tells the user what input in broken, what was passed in, and the reason | ||
why the value was invalid. All of this together gives the user the best chance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a personal preference, but I like this sort of info broken out into a list:
We recommend writing an error message that states:
- which parameter is raising the error
- what value was passed
- why the value is incorrect
doc/devel/contributing.rst
Outdated
In cases like this it may be possible to get into an interactive debugger and | ||
from reading the stack trace sort out right local variable to check is to start | ||
to sort out what went wrong. However, without access to the running process the user |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After the and
, this sentence kind of gets a bit muddled.
doc/devel/contributing.rst
Outdated
Internal helpers | ||
~~~~~~~~~~~~~~~~ | ||
|
||
Matplotlib has number of helper functions in the ``matplotlib._api`` module |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Matplotlib has number of helper functions in the ``matplotlib._api`` module | |
Matplotlib has a number of helper functions in the ``matplotlib._api`` module |
doc/devel/contributing.rst
Outdated
~~~~~~~~~~~~~~~~ | ||
|
||
Matplotlib has number of helper functions in the ``matplotlib._api`` module | ||
named as ``check_*`` which provide nice error messages for very common checks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
named as ``check_*`` which provide nice error messages for very common checks | |
named as ``check_*`` which provide nice error messages for common checks |
very seems superfluous?
doc/devel/contributing.rst
Outdated
|
||
This message tells the user what (local) variable Matplotlib checked was and | ||
what value was passed in which can help users rapidly find bugs in their own | ||
code. For example if they expected to have passed in an integer but the error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code. For example if they expected to have passed in an integer but the error | |
code. For example, if they expected to have passed in an integer but the error |
doc/devel/contributing.rst
Outdated
This message tells the user what (local) variable Matplotlib checked was and | ||
what value was passed in which can help users rapidly find bugs in their own | ||
code. For example if they expected to have passed in an integer but the error | ||
messages reports the string ``'aardvark'``, they may know where in their code |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
messages reports the string ``'aardvark'``, they may know where in their code | |
message reports the string ``'aardvark'``, they may know where in their code |
I'm missing info about dropping punctuation characters and if an error message should be in Sentence case or nor. |
Highly nitpicky, but my personal(?) view is to do what cpython does:
i.e. no leading capital and no trailing punctuation. |
I agree with others that this seems pretty verbose (though a good idea to document); a first try at editing (while keeping most of your wording) gives me Error messages should err on the side of being verbose, descriptive, and
specific about what went wrong. They should be informative enough so that a
typical user (not an expert of our API) can understand, debug, and fix their
problem based solely on the message, without the need to consult the online
documentation.
For example, input validation errors should include, where possible,
information about which input is invalid, what value was passed in, and why the
value is invalid, e.g. ::
raise ValueError(f"{value=!r} is invalid, value must be a positive integer")
This message helps the user to quickly diagnose and fix their problem.
Remember that many other libraries are implemented on top of Matplotlib, and
therefore ``value`` may not even have been directly passed by the user, but
rather generated in some intermediate layer. In such cases, this kind of
highly explicit messages can be particularly useful, compared to shorter
messages such as ::
raise ValueError("invalid value") |
Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com> Co-authored-by: Antony Lee <anntzer.lee@gmail.com> Co-authored-by: Oscar Gustafsson <oscar.gustafsson@gmail.com>
9a1a219
to
4ded56e
Compare
I took @anntzer 's wording whole sale and applied the other changes. |
-------------- | ||
|
||
|
||
Error messages should err on the side of being verbose, descriptive, and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-------------- | |
Error messages should err on the side of being verbose, descriptive, and | |
-------------- | |
Error messages should err on the side of being verbose, descriptive, and |
.. currentmodule:: matplotlib | ||
|
||
|
||
.. autosummary:: | ||
:toctree: _as_gen | ||
:template: autosummary.rst | ||
:nosignatures: | ||
|
||
_api.check_isinstance | ||
_api.check_in_list | ||
_api.check_shape | ||
_api.check_getitem |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These appear to already have been documented somewhere since the build is failing.
PR Summary
After leaving a comment to make error messages verbose I felt inspired to write it up for the docs...
Adding generated API docs for the private API might be a bit controversial, but I think on net it is the right thing to do so that we if we do remove them we can be sure that the docs do not still advocate for their use and saying "there are some
check_*
functions" felt too vague).