"Debug-friendly" pcall/xpcall Error Handling

As a Roblox developer, it is currently too hard to process lua errors within a pcall while maintaining clean stack traces and keeping a readable output.

If Roblox is able to address this issue, it would improve my development experience because it would allow my debugging experience to be much smoother.

The problem is that if I wish to catch errors in pcall or xpcall, I sacrifice keeping my output readable when errors do occur. Generally, developers will use xpcall if they wish to have a traceback for their errors and retrieving the stacktrace in the error callback via debug.traceback(), but there is no way to properly display that traceback in an error message.

The result is generally coming from something like error(errorMessage.."\n"..traceback). The problem with this is that while the traceback is readable, you get the line number where the traceback was created (in the xpcall error callback), you get a second stack trace where the error was sent to the console, you can’t jump to lines in the stack by clicking them like you can with any other error, and lastly, its not colored properly which makes it harder to differentiate between the error and the stack. Overall this results in errors that are very annoying to read and this hinders my debugging experience in a lot of ways.

I think that a solution to this issue should still allow for the same behaviours pcall and xpcall allow for, should (ideally) be as performant as it can be in reference to pcalling, but should make it possible to output caught errors the same as they normally would be without the pcall.

The solution I propose based on my own use case alone is to implement new pcall and xpcall modes which do not suppress the error they catch from going to the console. This could for example be called “loud pcall” and could be represented with lpcall and lxpcall.

An additional benefit of my proposal is that it would be possible to output console errors that don’t halt code without the use of spawn (which is slower than calling wait() and requires the thread to yield): lpcall(error, "This is an error in the caller function", 2)