I've written a few big scripts, and while doing so discovered much late that I had subtle bugs that would silently ruin things unexpectedly. (How many noticed I used "late" instead of "later"?) So I thought I'd share an LUA technique that I've recently adopted for my AC code, which has uncovered plenty of lurking nasties. Consider this: Code: hot = true if hot = nil then dream = 'waking' else dreams = 'walking' end print(dream) -- and you will get nil, not 'walking' even though "hot" is true The subtle plural on "dream". Or it could be a case like "nothaving ==" vs. "notHaving ==". Same result. A silent nasty. The code below fixes this. As long as every single variable used is declared as "local var" or "local var = ..." this metatable will catch typos in variables. The way it works is to flag undeclared global variable use as a warning. (To actually use a global, use "declare(var, init)".) So if you've a typo in a variable name it'll get spotted quickly before much debug logging ensues. Cheers. Code: -- Runtime global variable checking. Globals must be explicitly declared, which will catch variable name typos local declaredNames = {['vprint'] = true, ['vprinthex'] = true, ['maxgroup'] = true, ['mosquitto'] = true, ['ssl'] = true, } -- Reserved declarations that should be ignored local function declare(name, initval) rawset(_G, name, initval) declaredNames[name] = true end local exclude = {['ngx'] = true, } -- Reserved variable reads that should be ignored setmetatable(_G, { __newindex = function (t, n, v) if not declaredNames[n] then log('Warning: Write to undeclared global variable "'..n..'"') end rawset(t, n, v) end, __index = function (_, n) if not exclude[n] and not declaredNames[n] then log('Warning: Read undeclared global variable "'..n..'"') end return nil end, })