On a fresh install of TL 2018, on Linux, no tikz graph drawing libraries can be found.

The files, e.g. texlive/2018/texmf-dist/tex/generic/pgf/graphdrawing/tex/pgflibrarygraphdrawing.trees.code.tex are there.




Hello World


Compiling with lualatex yields ! Package pgf Error: Graph drawing library 'trees' not found.

  • 2
  • Do read this right, that pgf uses an internal function from luaotfload and that internal function got its API changed? – MaxNoe Sep 29 '18 at 21:02
  • Hell, dependency management in TeX is even worse than javascript, in javascript there it at least exists. – MaxNoe Sep 29 '18 at 21:03
  • @MaxNoe This is Lua code, not TeX, and the API concerned isn't one for font loading ... – Joseph Wright Sep 29 '18 at 21:11
  • @MaxNoe Also, as the change is a propagation from ConTeXt, and as the function concerned is almost certainly there specifically for ConTeXt support, I don't think one can really blame luaotfload. – Joseph Wright Sep 29 '18 at 21:14

As detailed in the https://github.com/u-fischer/luaotfload/issues/6, pgf_lookup_and_require wrongly uses resolvers.findfile to find the graph drawing libraries when used with ConTeXt. This bug surfaced when luaotfload was upgraded which now also the resolvers.findfile function.

The problem is clearly with PGF here, because resolvers.findfile is to find fonts and not arbitrary files in the TeX tree. Until this is fixed, you can override the pgf_lookup_and_require function with your own variant which does the correct thing.



function pgf_lookup_and_require(name)
    local sep = package.config:sub(1,1)
    local function lookup(name)
        local sub = name:gsub('%.',sep)  
        if kpse.find_file(sub, 'lua') then
        elseif kpse.find_file(sub, 'clua') then
            return false
        return true
        lookup('pgf.gd.' .. name .. '.library') or
        lookup('pgf.gd.' .. name) or
        lookup(name .. '.library') or



Hello World


It seems to me that the Lua code in PGF is not so well thought through as this simple function already exhibits some Lua antipatterns, such as polluting the global environment by require instead of returning a table and stopping and restarting the garbage collector, which forces a collection cycle. Also this clumsy way of determining the path separator instead of using package.config should really be avoided.

  • For determining path separator, what's wrong with os.type (as it's either windows or 'something else')? I've looked at package.config and felt that this approach is much less clear. – Joseph Wright Sep 30 '18 at 8:24
  • @JosephWright The package.config way is the documented way and hence preferred. I guess os.type would also be okay, but that is not what PGF is doing. PGF checks whether the entries in the PATH environment variable are delimited by ; (which is the case on Windows). Furthermore local sep = package.config:sub(1,1) takes only a single line. – Henri Menke Sep 30 '18 at 8:33
  • Sure: I'm thinking for l3build where we have quite a lot of things to do. I'd not looked at the pgf code: that sounds scary! – Joseph Wright Sep 30 '18 at 8:35
  • resolvers.findfile was already in luaotfload before, it only handled the lua type differently. – Ulrike Fischer Sep 30 '18 at 13:40
  • For anyone not willing to click through the issue, the bug was fixed in pgf. – Keith Prussing Feb 6 at 3:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.