Using Lua 5.4’s __close Metamethod for Deterministic Cleanup
Shows how the <close> attribute invokes __close automatically when a variable leaves scope, ensuring resources like files are released even on error.
22 Aug 2026, 00:01 UTC

Deterministic cleanup with Lua 5.4’s __close metamethod
Lua 5.4 introduces the __close metamethod, which can be triggered automatically when a local variable marked with the <close> attribute leaves its scope. This provides RAII‑style resource management without explicit pcall cleanup.
Worked example: automatic file closing
-- example.lua
local f = assert(io.open('tmp.txt', 'w'))
f:write('hello')
-- If an error occurs here, f:close() is still called
-- error('test') -- uncomment to test error path
The variable f is a file handle returned by io.open. File handles in Lua already implement __close that invokes the :close method. When the block ends—either normally or because of an error—the interpreter calls f:__close(), which closes the file.
How the mechanism works
- The
<close>attribute tells the compiler to generate a cleanup call for the variable when its scope ends. - The cleanup looks up the
__closemetamethod on the variable’s value (must be a table or userdata). - If the metamethod returns a value, that value is ignored; returning
nilis customary to avoid accidental reuse.
Limits and common mistakes
- Version requirement:
__closeand the<close>syntax exist only in Lua 5.4 and later. Lua 5.3, LuaJIT, and earlier versions will raise a syntax error. - The variable must hold a table or userdata that provides a
__closemetamethod. Applying<close>to a number, string, or plain function results in a syntax error. - If the
__closemethod does not returnnil, the interpreter may treat the returned value as the new variable contents, leading to unexpected behavior or multiple calls. - Using
<close>in tight loops adds a small overhead due to metamethod dispatch; for performance‑critical code consider manualclosecalls. - Code that relies on
<close>is not portable to older Lua runtimes. A portable fallback wraps the resource in apcallblock and calls the cleanup function explicitly in thefinally‑style section.
Verification steps (do not claim execution)
To check that the cleanup works:
- Run the script with a Lua 5.4 interpreter:
lua5.4 example.lua. - After execution, verify that
tmp.txtcontains exactly the stringhelloand that no file handle remains open (e.g., by checkinglsofon Unix or Process Explorer on Windows). - Optionally uncomment the
error('test')line, run again, and confirm the file is still closed and contains the written data.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.