TransWikia.com

Overwritten global Lua variables "attempt to index a NN value"

TeX - LaTeX Asked by uli_1973 on January 9, 2021

I have a Lua file (too old to remember what I did exactly) that includes this line:

local arg_cnt = debug.getinfo(formatter).nparams

which triggers an error with the message

attempt to index a boolean value (global 'debug')

debug is a Lua table with introspection functions, which I obviously wanted to use, and which has to have worked when I wrote the code maybe one or two years ago.

How can I determine why this doesn’t work anymore?

My initial suspicion in that type of cases is that debug is overwritten at some point, but all kind of searching and grepping doesn’t point me to a place where that might happen.

Is it possible that there have been changes to the core so I have to explicitly activate the debug table? I’m on the current Ubuntu version’s repository version with

lualatex --version
This is LuaHBTeX, Version 1.12.0 (TeX Live 2020/Debian)

2 Answers

This is not a concrete answer to the question, but I'd like to write a generic answer anyway.

attempt to index a boolean value (global 'debug')

is a Lua error message which tells you that you are attempting to use a member of a Lua table, but what you treat as a table is not a table (anymore).

In my case I tried to call the function getinfo() from the table debug (which is built into Lua and should be available anywhere), but when invoking it Lua found a boolean value (true or false) instead.

It is very likely that this observation indicates that the builtin table debug has at some point been overwritten with a boolean, either in your preamble or - as a bug - in a package.

To find the culprit it is useful to insert

directlua{print(debug)}
directlua{debug.go}

in your preamble as suggested in this comment. The first line will print the table address - as long as there still is a table - the second line will cause an error and stop the compilation. You can iterate through every step of your preamble to find exactly where the problem starts.

Underlying problem

The reason for this issue is a typical Lua programming error, in this case in a package. In order to create a status flag the package contained the line

debug = false

setting the debug variable to false as its default value, which is then used in a function outputting debug information.

The problem is that in Lua variables are by default in the global namespace (opposite behaviour from e.g. Python) - which means that the line above overwrites the global variable and effectively "kills" the whole builtin Lua table.

This is a very good example for the advice never to forget using local variables in Lua wherever possible:

local debug = false

This way debug is local to the current module and does not affect the global table with the same name.

Answered by uli_1973 on January 9, 2021

When trying to find out who is responsible for changing global variables in Lua, it is sometimes useful to temporarily assign a metatable to the global table. (I strongly recommend never to do this outside of debugging and to let the metatable work as close to a normal tableas possible, otherwise you get all kinds of weird behavior.)

So, in order to detect changes to the global debug through metamethods, you have to delete the debug table. You can virtually put it back though the __index metamethod. Then you can use __newindex to detect attempts create a new global debug in which case you can print a warning, using the original debug table to get information about the responsible Lua function. In isn't that helpful though if it was reset e.g. in directlua, but you can use LuaTeX's status table to additionally provide the current TeX file and line.

Of yourse you have to do this before loading anything which might be responsble, do it's best to put it even before documentclass:

directlua{
  local debug = debug
  local traceback, getinfo = debug.traceback, debug.getinfo
  _G.debug = nil
  setmetatable(_G, {
    __index = {debug = debug},
    __newindex = function(t, k, v)
      if k == "debug" then
        local guilty = getinfo(2)
        texio.write_nl("We found the naughty party: " .. (guilty.name or "nameless devil") .. " in " .. guilty.source .. " at line " .. guilty.currentline)
        texio.write_nl("TeX is currently reading " .. status.filename .. " at line " .. status.linenumber)
      end
      return rawset(t, k, v)
    end,
  })
}
documentclass{article}
usepackage{grandmother}
begin{document}
end{document}

which would e.g. provide the output

...
(/usr/local/texlive/2020/texmf-dist/tex/latex/base/size10.clo))
(./grandmother.sty
We found the naughty party: rose_tylor in @./bad_wolf.lua at line 2
TeX is currently reading ./grandmother.sty at line 4)
(/usr/local/texlive/2020/texmf-dist/tex/latex/l3backend/l3backend-luatex.def)
...

indicating that a function rose_tylor in the file ./bad_wolf.lua is changing debug, the change happens in line 2 of the file and it is loaded in grandmother.sty on line 4.

Answered by Marcel Krüger on January 9, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP