When something goes wrong
Every script has mistakes in it at some point. Luawe tries to say plainly what is wrong and where. This page shows the kinds of mistake there are, how to read what the game says about them, and how a script can deal with trouble itself.
Mistakes the editor sees
Some mistakes show before the level runs. The editor looks a script over as you type.
A red line marks text that is not Luawe at all: a missing end, a bracket that is never closed, a word in the wrong place. A script with a red line cannot run. The message, under the mouse and below the box, says what was expected:
It prints
the 'if' on line 3 is never closed: it needs 'end' (found the end of the script)A yellow line marks something that is Luawe but looks wrong, most often a name that nothing gives a value to. That is nearly always a typing mistake, and the editor guesses what was meant:
It prints
'prnt' has no value: nothing in this script gives it one (did you mean 'print'?)
'things' has nothing called 'fnd' (did you mean 'find'?)A script with yellow lines does run. Whether it works is another matter.
Mistakes that show while the level runs
Other mistakes only show when the line is reached. The task stops there, and the script output says what happened in red, with the script's name and the line:
It prints
door.luawe:12: attempt to index a nil value (variable 'door') (reading 'tween')Click the line in the script output to go to that line of the script.
Only the task that hit the mistake stops. The level carries on, and so do the other scripts and every other task of this one.
Reading the messages
| The script output says | It means |
|---|---|
attempt to index a nil value (variable 'door') | door is nil, and the script asked it for something (door.x, door:tween()). Often things.find did not find the thing: check its name |
attempt to call a nil value (global 'prnt') | There is no function called that. Look for a typing mistake |
attempt to do arithmetic on a nil value | A value in a sum is missing |
attempt to do arithmetic on a string value | Text was used as a number: use tonumber() |
attempt to compare number with string | < and > need two numbers or two strings |
attempt to concatenate a nil value | A value joined with .. is missing |
this thing is gone | The thing was destroyed, or its time was up. Ask thing.exists first |
this task ran for too long without waiting | A loop went on and on. Put a wait() in it |
Saying that something is wrong
error stops the task with a message of your own. assert does so when a value is false or nil, and otherwise gives the value back, which makes it a good guard:
local door = assert(things.find("door"), "this script needs a thing called door")
door.alpha = 0.5If the level has no thing called door, the script output says so in your words, instead of failing later with something harder to read.
warn writes a yellow line to the script output and carries on. Use it for what is odd but not fatal.
Catching a mistake
pcall calls a function and catches whatever goes wrong inside it. It gives true and the function's results, or false and the error:
local function risky(n)
if n > 2 then
error("too big: " .. n)
end
return n * 10
end
print(pcall(risky, 1))
print(pcall(risky, 5))It prints
true 10
false door.luawe:3: too big: 5The error is the message, with where it happened put before it. error(message, 0) leaves the place out.
An error need not be text. Any value can be thrown, and pcall hands back that very value:
local ok, problem = pcall(function()
error({ code = 7, reason = "no key" })
end)
print(ok, problem.code, problem.reason)It prints
false 7 no keyxpcall is pcall with a function that looks at the error first, for example to add where the script was:
local ok, report = xpcall(function()
local missing = nil
return missing.x
end, function(message)
return "caught: " .. message
end)
print(ok, report)It prints
false caught: door.luawe:3: attempt to index a nil value (variable 'missing') (reading 'x')Finding out what a script does
There is no debugger. The tools are the ones every programmer uses first:
printthe values you are unsure of.print("got here", lives, door)costs nothing and answers most questions. A thing prints as what it is, for exampleblock "door" #3.type(value)says what kind of value something is.debug.traceback()gives the lines of the functions that called each other to get to where the script is now, as text to print.
local function inner()
print(debug.traceback("how did we get here?"))
end
local function outer()
inner()
end
outer()It prints
how did we get here?
door.luawe:2: in function 'inner'
door.luawe:5: in function 'outer'
door.luawe:7: in the scriptIn a test play, what scripts print also shows in a corner of the screen for a few seconds, so you can watch a value while playing.