Lua 5.1's API provides an error() function, which accepts a string (the error message) and a "level".
My understanding is that level
, lets you move up the call stack, so you can provide nicer error reporting, especially when delivering a module as an API.
For example, imagine the user calls api_function(x)
with x = nil
. This will be an error, but the API doesn't know until it's quite a bit into it's code.
It may result in this call stack:
api_function(x) : user_file.lua:30
-> api_function : api.lua:20
-> some_function : api.lua:250
-> handle_when_x_string : api_string.lua:20
-> error("value is nil") : api_string.lua:66
As written, the user will see something like api_string.lua:66 error: value is nil
, when what they really want to see the "nice" error, user_file.lua:30 error: value is nil
. ("Is that error my fault or a bug in the API?")
Now, we can change the code to "pop the call stack",
api_function(x) : user_file.lua:30
-> api_function : api.lua:20
-> some_function : api.lua:250
-> handle_when_x_string : api_string.lua:20
-> error("value is nil", 5) : api_string.lua:66
Which will return the "nice" error, but, imagine you can also call handle_when_x_string
more directly (poor API design aside),
another_api_fn(x) : user_file.lua:44
-> another_api_fn : api.lua:11
-> handle_when_x_string : api_string.lua:20
-> error("value is nil", 5) : api_string.lua:66
Now our "pop level" is incorrect. Perhaps in this example, it would simply pop to the top and stop trying, but the principle of "incorrect level" remains at least uncomfortable, it may even pop "out" of where the user caused the error.
I can see a few solutions:
- Don't set level and just assume the user is smart enough to work it out.
- Wrap anything below your api entry points (
api_function
&another_api_fn
) in a pcall, catch any error and re-bubble with a known "good" level value. - Don't ever error in lower api functions, always
return nil, error
or some similar pattern, then check for that inapi_function
and act as required.
My questions are:
- Is it a problem to return the wrong level? It seems poor form to just "yeah whatever" a number in there and hope it's good.
- If it is a problem, when is it ever a good practice to set the level (beyond maybe 0 which disables location reporting)
- Which of the solutions, if any, are best practice? What should I actually do to write better maintainable code? Wrapping in pcall seems the easiest, since you can still rely on "normal errors" when testing and your functions are somewhat simpler, but somehow it feels like an antipattern, in my head.