I want to move all .lua files into the subdirectory code to avoid polluting the main directory with them. However, I cannot get lualatex to find them there.

Given this project layout:




\directlua{package.path = './code/?.lua;' .. package.path}



package.path = './code/?.lua;' .. package.path





When I run lualatex main.tex I get the output:

This is LuaTeX, Version beta-0.79.1 (TeX Live 2014/Arch Linux) (rev 4971) 
 restricted \write18 enabled.
LaTeX2e <2014/05/01>
Babel <3.9k> and hyphenation patterns for 79 languages loaded.
Document Class: article 2007/10/19 v1.4h Standard LaTeX document class

! LuaTeX error [\directlua]:1: module 'test' not found:
        no field package.preload['test']
        [kpse lua searcher] file not found: 'test'
        [kpse C searcher] file not found: 'test'
stack traceback:
        [C]: in function 'require'
        [\directlua]:1: in main chunk.
l.5 \directlua{require('test')}

? q
OK, entering \batchmode

The problem seems to be that lualatex does not find the files in the subdirectory although I altered the package.path (which is also printed correctly!).

When I runt the same code via lua main.lua the output is


as expected.

For some reason lualatex seems not to take package.path into account.

Using require('code/test.lua') is not an option because then the dependency between test.lua and test2.lua is not picked up correctly.

What do I need to do to make lualatex find my .lua files in the code directory?

I already followed this question to this answer but I don't see how this solves the problem (or does it state that we cannot change the package search path in lualatex?). Also, the scenario seems to be another one as I don't want to "install a systemwide" module but some scripts for this project only.

  • 2
    lualatex doesn't use package path by default. it uses kpse library which searches in texmf tree abd current directory. but it is possible to modify package loader to support package oath, see tex.stackexchange.com/a/219228/2891
    – michal.h21
    Jan 6, 2015 at 14:20
  • @michal.h21 So while overriding the "easy to use" default algorithm they (the lualatex authors) did not offer a replacement/command to add your own paths? I feel like it might not be an otherworldly request to be able to use subdirectories in your lua(latex) code. Jan 6, 2015 at 14:38
  • you have an error in your code: require('code/test') should be require('code.test'). but it probably will not find submodules anyway
    – michal.h21
    Jan 6, 2015 at 14:54
  • try require('code.test') it should work. Jan 6, 2015 at 15:00
  • @YiannisLazarides michal.h21: require(code/test) works as well as require(code.test) the problem occurs with the dependency in code/test.lua to code/test2.lua which in both cases does not work because the require does not search in code. Jan 6, 2015 at 15:25

2 Answers 2


The fastest way I have found to import relative packages in lualatex is

require(package.searchpath('test', './?.lua:./code/?.lua'))

which will find test.lua by searching ./ and ./code. It is hacky, but also clear and quick.

Adding the path loader as in https://tex.stackexchange.com/a/219228/2891 is the more thorough solution, but that code did not immediately work for me, plus it would require figuring out the textmf lua paths.

  • A Warm Welcome to TeX.SE!
    – A Feldman
    Jul 14, 2016 at 2:08
  • The solution works, but I believe the appropriate path separator is the semicolon. That makes it work for me. May 26, 2019 at 5:33
  • This is good for a single file, but if your lua library has multiple files (ie is a folder with several files in it), it will be problematic. I recommend placing the files where lualatex.exe is (in my case C:\Program Files\MiKTeX 2.9\miktex\bin\x64) and usepackage{luapackageloader} Jul 26, 2021 at 18:58
local oldreq = require
require = function(p) 
    return oldreq(package.searchpath(p, './?.lua;./code/?.lua'))
  • 1
    Welcome to TeX.SX! Can you please explain what your shown code does? How does it solve the given issue? Please do not only throw a code, explain what is does.
    – Mensch
    Sep 27, 2019 at 17:24

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.