REFramework Lua Error Handling and Debugging Guide

Writing Lua scripts for REFramework is forgiving in most ways, but errors still happen, and when they do, the way REFramework reports them is not always obvious if you haven’t run into it before. This guide covers how errors actually surface in REFramework, how to read what the framework is telling you, and the practical habits that catch problems before they become confusing to track down.

Two kinds of errors, two kinds of feedback

REFramework treats startup errors and runtime errors differently, and knowing which one you’re dealing with changes where you should be looking.

A startup error happens the moment a script loads, usually because of a syntax mistake or a typo in a function name. REFramework catches these immediately and throws a MessageBox describing what went wrong, along with a line number. This is the easier category to deal with, since the game pauses for you and hands you the answer directly.

A runtime error happens later, once the script is already running and something goes wrong inside a callback, like on_frame or on_update. REFramework deliberately does not pop up a MessageBox for these, because interrupting the game mid-session every time a script hits a problem would make the framework unusable. Instead, runtime errors get written to the debug log, which means you need to actually be watching that log to catch them.

Reading the debug log

The debug log is where most real debugging happens once a script is past its initial load. REFramework writes to it using the standard Windows OutputDebugString mechanism, which means you need a tool capable of capturing that output. DebugView, a free Sysinternals utility from Microsoft, is built for exactly this and is the standard choice for reading REFramework’s runtime output in real time.

Run DebugView before launching the game, and it will pick up REFramework’s log output as it happens, including any Lua errors thrown from inside a callback. This is a much faster feedback loop than guessing what broke based on symptoms in-game, since the actual error message and stack trace show up as soon as the problem occurs. Setting up DebugView once and leaving it running in the background while you work on a script costs nothing and saves you from missing an error that would otherwise pass by silently.

Using pcall to catch errors yourself

Lua’s built-in pcall function lets you catch an error inside your own script instead of letting it propagate up and potentially stop the rest of your script from running. This matters in REFramework specifically because a single unguarded error inside a callback can silently break the rest of that script’s logic for the remainder of the session.

Wrapping a risky call in pcall looks like this:

local success, err = pcall(function()
    -- code that might fail
end)

if not success then
    print("Something went wrong: " .. tostring(err))
end

If the wrapped code fails, pcall returns false along with the error message, instead of letting the error crash the callback outright. This is particularly useful around any code that depends on something that might not exist yet, like a managed object that hasn’t loaded, since that is one of the most common sources of runtime errors in REFramework scripts.

For anything beyond a simple catch, the official Lua 5.1 reference manual covers pcall, xpcall, and the error function in detail, and REFramework’s Lua environment follows this same 5.1 behavior.

Common error types and what they usually mean

Error message patternUsual causeWhere to look
attempt to index a nil valueTrying to use an object that doesn’t exist yetCheck that the managed object or field was actually retrieved before use
attempt to call a nil valueMisspelled function name, or the API function doesn’t exist in this REFramework versionCompare against the current API reference
Script loads but nothing happensNo syntax error, but the script’s logic never triggersConfirm the callback name is correct and actually registered
Error only appears intermittentlyObject exists sometimes but not always, often during scene transitionsWrap the access in pcall or add a nil check before use

A practical debugging workflow

When a script isn’t behaving and the cause isn’t obvious from the error message alone, working through it in order saves time compared to guessing.

  1. Check for a MessageBox first. If one appeared, the error and line number are already given, so start there.
  2. If no MessageBox appeared but something is clearly wrong, open DebugView and reproduce the issue while watching the log for a Lua error.
  3. If the log shows an error involving a nil value, add a print statement or a pcall wrapper immediately before the failing line to confirm exactly what is nil and when.
  4. Once the failing condition is identified, decide whether to guard against it with a nil check or restructure the script so that condition can’t occur.

This sequence works because it moves from the fastest possible answer, a MessageBox that tells you outright, down to the slowest, adding your own diagnostic code, only when the faster options don’t give you enough information.

Writing scripts that fail less often

A few habits reduce how often you need to debug in the first place.

  • Check that an object is not nil before using it, especially anything retrieved through sdk.get_managed_singleton or similar calls that can return nothing during certain game states
  • Keep frequently reused values in local variables rather than re-fetching them every frame, which also reduces the number of places a nil check needs to happen
  • Use simple print statements during development to confirm a section of code is actually being reached before assuming the logic itself is wrong. REFramework’s plugin API exposes dedicated logging functions as well, worth checking in the current API reference if you want leveled logging instead of plain print output

Conclusion

Most REFramework Lua errors fall into one of two categories: startup errors that the framework hands you directly through a MessageBox, and runtime errors that only show up in the debug log unless you’re watching for them with a tool like DebugView. Knowing which category you’re dealing with, wrapping risky calls in pcall, and working through a MessageBox first, log second, manual diagnostics last approach turns most debugging sessions from guesswork into a short, direct process. If a lot of this doesn’t match what you’re seeing on your current setup, it’s worth checking whether you’re on an older REFramework build first, since fixes to the scripting environment land in updates fairly often.