Get a 'clear' error message in Lua - error-handling

I am using the error function in quite a few of my functions and would like to propagate the error messages to the user. However, I obviously don't want to include information about where the error occured exactly; this information should only go to the log files.
For example, I have a class that manages the connection to a server. If the connection times out, it calls
error("Connection timed out!")
The error message is then caught by the calling code via pcall. However, the message contains not only the message I passed, but also the name of the file that caused the error and the line number:
common/net/enetclient.lua:21: Connection timed out!
The question is: Is there any way to only retrieve the error message itself, or do I have to do this manually like following:
local status, msg = pcall(someFunctionThatThrowsErrors)
if not status then
local file, msg = msg:match("(.-:%d+): (.+)")
print("Error: " .. msg)
end
Cheers,

From the documentation of the error function:
error (message [, level])
Terminates the last protected function called and returns message as the error message. Function error never returns.
Usually, error adds some information about the error position at the beginning of the message, if the message is a string. The level argument specifies how to get the error position. With level 1 (the default), the error position is where the error function was called. Level 2 points the error to where the function that called error was called; and so on. Passing a level 0 avoids the addition of error position information to the message.
From what is stated in the second paragraph, adding a level of 0 to the error call will result in the desired output:
error("Connection timed out!", 0)

Related

Debugging "Transaction simulation failed" when sending program instruction (Solana Solidity)

When attempting to make a call to a program compiled with #solana/solidity, I'm getting the following error:
Transaction simulation failed: Error processing Instruction 0: Program failed to complete
Program jdN1wZjg5P4xi718DG2HraGuxVx1mM7ebjXpxbJ5R3N invoke [1]
Program log: pxKTQePwHC9MiR52J5AYaRtSLAtkVfcoGS3GaLD24YX
Program log: sender account missing from transaction
Program jdN1wZjg5P4xi718DG2HraGuxVx1mM7ebjXpxbJ5R3N consumed 200000 of 200000 compute units
Program failed to complete: BPF program Panicked in solana.c at 285:0
Program jdN1wZjg5P4xi718DG2HraGuxVx1mM7ebjXpxbJ5R3N failed: Program failed to complete
jdN1wZjg5P4xi718DG2HraGuxVx1mM7ebjXpxbJ5R3N is the program's public key and pxKTQePwHC9MiR52J5AYaRtSLAtkVfcoGS3GaLD24YX is the sender's public key.
I'm using a fork of the #solana/solidity library that exposes the Transaction object so that it can be signed and sent by Phantom Wallet on the front end. The code that results in the error is as follows:
// Generate the transaction
const transaction = contract.transactions.send(...args);
// Add recent blockhash and fee payer
const recentBlockhash = (await connection.getRecentBlockhash()).blockhash;
transaction.recentBlockhash = recentBlockhash;
transaction.feePayer = provider.publicKey;
// Sign and send the transaction (throws an error)
const res = await provider.signAndSendTransaction(transaction);
I would attempt to debug this further myself, but I'm not sure where to start. Looking up the error message hasn't yielded any results and the error message isn't very descriptive. I'm not sure if this error is occurring within the program execution itself or if it's an issue with the composition of the transaction object. If it is an issue within the program execution, is there a way for me to add logs to my solidity code? If it's an issue with the transaction object, what could be missing? How can I better debug issues like this?
Thank you for any help.
Edit: I'm getting a different error now, although I haven't changed any of the provided code. The error message is now the following:
Phantom - RPC Error: Transaction creation failed. {code: -32003, message: 'Transaction creation failed.'}
Unfortunately this error message is even less helpful than the last one. I'm not sure if Phantom Wallet was updated or if a project dependency was updated at some point, but given the vague nature of both of these error messages and the fact that none of my code has changed, I believe they're being caused by the same issue. Again, any help or debugging tips are appreciated.
I was able to solve this issue, and although I've run into another issue it's not related to the contents of this question so I'll post it separately.
Regarding my edit, I found that the difference between the error messages came down to how I was sending the transaction. At first, I tried sending it with Phantom's .signAndSendTransaction() method, which yielded the second error message (listed under my edit). Then I tried signing & sending the transaction manually, like so:
const signed = await provider.request({
method: 'signTransaction',
params: {
message: bs58.encode(transaction.serializeMessage()),
},
});
const signature = bs58.decode(signed.signature);
transaction.addSignature(provider.publicKey, signature);
await connection.sendRawTransaction(transaction.serialize())
Which yielded the more verbose error included in my original post. That error message did turn out to be helpful once I realized what to look for -- the sending account's public key was missing from the keys field on the TransactionInstruction on the Transaction. I added it in my fork of the #solana/solidity library and the error went away.
In short, the way I was able to debug this was by
Using provider.request({ method: 'signTransaction' }) and connection.sendRawTransaction(transaction) rather than Phantom's provider.signAndSendTransaction() method for a more verbose error message
Logging the transaction object and inspecting the instructions closely
I hope this helps someone else in the future.

How would I print out errors?

In the software called Roblox studio I need help making a script that whenever an error happens in game, it would print out the error again using the normal print function something like this example here:
Local error = —-whatever the error that happened was
Print(error) —- so it just simply prints it back out
Roblox provides a few different ways to keep track of when errors are thrown in your Scripts and LocalScripts.
If you want to observe errors locally in a script, and you know a specific chunk of code may throw errors, you can use pcall() as a try-catch block.
local success, result = pcall(function()
error("this is a test error message")
end)
if not success then
print("An error was thrown!")
print(result) --"this is a test error message"
end
If you want to observe errors across all of your scripts, you can attach a callback to the ScriptContext.Error signal. This signal fires any time any error is thrown. It provides information about the error, including the message, the callstack, and a reference to the script that threw the error.
Warning : ScriptContext.Error only fires in the context of the script that registers it. A Script will only observe errors thrown in server scripts, and registering in a LocalScript will only observe errors thrown on the client.
local ScriptContext = game:GetService("ScriptContext")
ScriptContext.Error:Connect( function(message, stack, context)
print("An error was thrown!")
print("Message : ", message)
print("Stack : ", stack)
print("Context :", context:GetFullName())
end)
Similarly, if you only care about the error messages themselves, you can also observe them being printed out to the Output window using the LogService.MessageOut signal. This signal fires any time anything is logged to Output. This includes messages, warnings, and errors.
local LogService = game:GetService("LogService")
LogService.MessageOut:Connect( function(message, messageType)
if messageType == Enum.MessageType.MessageError then
print("An error was thrown!")
print(message)
end
end)
Use the stderr stream from io library to print debug messages.
-- Define debug function based in print
function debug(...) io.stderr:write(table.concat({...}, '\9') .. '\n') end
-- Debug acts as a regular "print()", but it writes to stderr instead
debug('[filename.lua]', 'debug')
Use "error()" function to print errors.
if true then
error("It should not be true!")
end
If you want to catch errors from a function, use xpcall()
-- Define debug
function debug(...) io.stderr:write(table.concat({...}, '\9') .. '\n') end
xpcall(
function()
local b = {}
-- This will throw an error because you cant index nil values
print(a.b)
end,
function(err)
debug('[xpcall]', err)
end
)
xpcall() wont stop the execution in case of error, so you only need to encapsulate your code in it if you want to catch any unexpected errors at runtime.

How do you throw Lua error up?

Is it possible to throw a Lua error from a function to be handled by the script calling the function?
For example the following will throw an error at indicated comment
local function aSimpleFunction(...)
string.format(...) -- Error is indicated to be here
end
aSimpleFunction("An example function: %i",nil)
But what I would rather do is catch the error and throw out a custom error by the function caller
local function aSimpleFunction(...)
if pcall(function(...)
string.format(...)
end) == false then
-- I want to throw a custom error to whatever is making the call to this function
end
end
aSimpleFunction("An example function: %i",nil) -- Want the error to start unwinding here
The intention being that in my actual use cases my functions would be more complicated and I would like to provide more meaningful error messages
The stack level of an error can be specified when throwing a new error
error("Error Message") -- Throws at the current stack
error("Error Message",2) -- Throws to the caller
error("Error Message",3) -- Throws to the caller after that
Usually, error adds some information about the error position at the beginning of the message. The level argument specifies how to get the error position. With level 1 (the default), the error position is where the error function was called. Level 2 points the error to where the function that called error was called; and so on. Passing a level 0 avoids the addition of error position information to the message.
Using the example given in the question
local function aSimpleFunction(...)
if pcall(function(...)
string.format(...)
end) == false then
error("Function cannot format text",2)
end
end
aSimpleFunction("An example function: %i",nil) --Error appears here
Use the error function.
error("something went wrong!")
Catching an error is as simple as using pcall
My_Error()
--Error Somehow
end
local success,err = pcall(My_Error)
if not success then
error(err)
end
Undoubtedly you're asking how this works. Well pcall runs a function in a protected thread (protected-call) and returns a bool, if it ran successfully, and a value (what it returned/the error).
Also don't think this means arguments to the function are impossible, simply pass them to pcall as well:
My_Error(x)
print(x)
--Error Somehow
end
local success,err = pcall(My_Error, "hi")
if not success then
error(err)
end
For more error handling control, see http://www.lua.org/manual/5.3/manual.html#2.3 and http://wiki.roblox.com/index.php?title=Function_dump/Basic_functions#xpcall

Getting "Connection is not recognized as a valid connection manager type" error in SSIS 2008 R2, but package runs fine

One of my primary SSIS import packages has been showing the following error the last few times it's been run. The data loads exactly how it should, just with this one error which doesn't seem to make a real difference. I would like to get it cleared up though.
Here is the error:
Error 1 Error loading Update.dtsx: The connection type "OLEDB" specified for connection manager "SQL.Staging" is not recognized as a valid connection manager type. This error is returned when an attempt is made to create a connection manager for an unknown connection type. Check the spelling in the connection type name. D:\SSIS Projects\Update.dtsx 1 1
Error 2 Error loading Update.dtsx: Error loading value " 0 SQL.Staging {925404E7-27AA-4C4E-337B-D6058341" from node "DTS:ConnectionManager". D:\SSIS Projects\Update.dtsx 1 1
Error 3 Error loading 'Update.dtsx' : The package failed to load due to error 0xC0010014 "One or more error occurred. There should be more specific errors preceding this one that explains the details of the errors. This message is used as a return value from functions that encounter errors.". This occurs when CPackage::LoadFromXML fails. . D:\SSIS Projects\Update.dtsx 1 1
As I said, the package runs fine. It doesn't seem to have any issues with the OLEDB source or destination's, which is what the error seems to indicate. Any other recommendations? Thanks!

How to make Xlib print error message, but not exit?

"The action of the default handlers is to print an explanatory message and exit." (link)
Example of such message:
X Error of failed request: BadWindow (invalid Window parameter)
Major opcode of failed request: 12 (X_ConfigureWindow)
Resource id in failed request: 0xc0007a
Serial number of failed request: 140
Current serial number in output stream: 141
If I set (XSetErrorHandler) my own "ignore everything" error handler, the "explanatory messages" disappear.
How to make Xlib ignore errors, but still print error messages?
If you actually want those error messages you pretty much have two options:
Pull _XPrintDefaultError out of XlibInt.c along with some private headers (with all the caveats of using library-private definitions).
Redefine exit() not to actually exit when _XDefautError calls it.
Neither is especially pretty and both may break and reduce your portability, but they do work.
You have to format your own message. The contents of the message is the contents of the XErrorEvent struct:
http://tronche.com/gui/x/xlib/event-handling/protocol-errors/default-handlers.html