Debug
Extended debug library functions for inspecting and modifying function internals at runtime. These functions are available both as globals and under the debug table (e.g., debug.getstack and getstack).
debug.getstack
Returns the value(s) on the stack at the given level. Can optionally accept a thread as the first argument.
debug.getstack(level: number, index: number?) -> any
debug.getstack(thread: thread, level: number, index: number?) -> any| Parameter | Type | Description |
|---|---|---|
thread | thread? | Optional thread to inspect |
level | number | Stack level to inspect |
index | number? | Specific stack index, or all values if omitted |
Example
local function test()
local a = 10
local b = "hello"
print(debug.getstack(1)) --> 10, "hello"
print(debug.getstack(1, 1)) --> 10
end
test()
-- With thread argument
local co = coroutine.create(function()
local x = 42
coroutine.yield()
end)
coroutine.resume(co)
print(debug.getstack(co, 1, 1)) --> 42debug.setstack
Sets a value on the stack at the given level and index. Can optionally accept a thread as the first argument.
debug.setstack(level: number, index: number, value: any) -> void
debug.setstack(thread: thread, level: number, index: number, value: any) -> void| Parameter | Type | Description |
|---|---|---|
thread | thread? | Optional thread to modify |
level | number | Stack level to modify |
index | number | Stack index to set |
value | any | The new value |
Example
local function test()
local x = 10
debug.setstack(1, 1, 999)
print(x) --> 999
end
test()debug.getconstants
Returns a table of all constants in a function's bytecode.
debug.getconstants(func: function | number) -> table| Parameter | Type | Description |
|---|---|---|
func | function | number | The function or stack level |
Example
local function test()
local x = "hello"
print(x)
end
local constants = debug.getconstants(test)
for i, v in pairs(constants) do
print(i, v) --> 1 "hello", 2 "print"
enddebug.getconstant
Returns a specific constant at the given index.
debug.getconstant(func: function | number, index: number) -> any| Parameter | Type | Description |
|---|---|---|
func | function | number | The function or stack level |
index | number | The constant index |
Example
local function test()
print("hello")
end
print(debug.getconstant(test, 1)) --> "print"debug.setconstant
Sets a constant at the given index in a function's bytecode.
debug.setconstant(func: function | number, index: number, value: any) -> void| Parameter | Type | Description |
|---|---|---|
func | function | number | The function or stack level |
index | number | The constant index |
value | any | The new constant value |
Example
local function greet()
print("hello")
end
debug.setconstant(greet, 2, "goodbye")
greet() --> goodbyedebug.getupvalues
Returns a table of all upvalues of a function.
debug.getupvalues(func: function | number) -> table| Parameter | Type | Description |
|---|---|---|
func | function | number | The function or stack level |
Example
local secret = "password123"
local function getSecret()
return secret
end
local upvalues = debug.getupvalues(getSecret)
for i, v in pairs(upvalues) do
print(i, v) --> 1 "password123"
enddebug.getupvalue
Returns a specific upvalue at the given index.
debug.getupvalue(func: function | number, index: number) -> any| Parameter | Type | Description |
|---|---|---|
func | function | number | The function or stack level |
index | number | The upvalue index |
Example
local counter = 0
local function increment()
counter = counter + 1
end
print(debug.getupvalue(increment, 1)) --> 0debug.setupvalue
Sets a specific upvalue at the given index.
debug.setupvalue(func: function | number, index: number, value: any) -> void| Parameter | Type | Description |
|---|---|---|
func | function | number | The function or stack level |
index | number | The upvalue index |
value | any | The new value |
Example
local counter = 0
local function getCounter()
return counter
end
debug.setupvalue(getCounter, 1, 100)
print(getCounter()) --> 100debug.getprotos
Returns a table of all inner (proto) functions defined within a function.
debug.getprotos(func: function | number) -> table| Parameter | Type | Description |
|---|---|---|
func | function | number | The function or stack level |
Example
local function outer()
local function inner1() end
local function inner2() end
end
local protos = debug.getprotos(outer)
print(#protos) --> 2debug.getproto
Returns a specific proto (inner function) at the given index.
debug.getproto(func: function | number, index: number) -> function| Parameter | Type | Description |
|---|---|---|
func | function | number | The function or stack level |
index | number | The proto index |
Example
local function outer()
local function inner()
return "inner function"
end
end
local proto = debug.getproto(outer, 1)
print(proto()) --> "inner function"debug.getinfo
Returns a table of information about a function.
debug.getinfo(func: function | number) -> table| Parameter | Type | Description |
|---|---|---|
func | function | number | The function or stack level |
Returned Table
| Key | Type | Description |
|---|---|---|
source | string | Source file/chunk name |
name | string | Function name (if available) |
what | string | "Lua", "C", or "main" |
currentline | number | Current executing line |
nups | number | Number of upvalues |
numparams | number | Number of parameters |
is_vararg | boolean | Whether function accepts varargs |
Example
local function myFunc(a, b, c)
print(a, b, c)
end
local info = debug.getinfo(myFunc)
print(info.name) --> "myFunc"
print(info.numparams) --> 3
print(info.nups) --> 0debug.validlevel
Returns true if the given stack level is valid (exists).
Aliases: isvalidlevel
debug.validlevel(level: number) -> booleanExample
print(debug.validlevel(1)) --> true
print(debug.validlevel(999)) --> falsedebug.getfenv
Gets the environment of a function or stack level. Works the same as getfenv, but is required inside oth hooks — when a stack level is provided, it automatically uses the original thread.
Global alias: dgetfenv
debug.getfenv(func_or_level: function | number) -> table| Parameter | Type | Description |
|---|---|---|
func_or_level | function | number | The function or stack level to get the environment of |
WARNING
Inside oth hooks, always use debug.getfenv instead of getfenv. When you pass a stack level, debug.getfenv will use the original thread rather than the hook thread, giving you the correct caller environment.
Example
local function test()
return "hello"
end
local env = debug.getfenv(test)
print(env == getfenv(0)) --> true (default environment)
-- Inside an oth hook:
oth.hook(some_func, function(...)
-- Use debug.getfenv with a level - uses original thread automatically
local caller_env = debug.getfenv(2)
return oth.get_root_callback()(...)
end)