Requires
Requires by Roblox instance path
Section titled “Requires by Roblox instance path”In run-server, and in edit without rojo-project, Luau Run builds the test
place itself.
For a spec that requires by instance path, such as
require(ReplicatedStorage.Shared.Thing), Luau Run needs to know which file
that path means. Name the Rojo project that builds your place:
[test.roblox-studio]rojo-project = "test.project.json"rojo-project is a path to a *.project.json that builds a place. Without it,
the lane follows only string requires. luau-run init writes it, and when that
project mounts your specs, init also sets data-model = "edit" to run them in
your whole place.
Before Studio starts, Rojo writes the project’s sourcemap. Luau Run follows each require through it to a file, and places the file in the test place at the path the project gives it. Only the modules a spec reaches are placed, and only ModuleScripts get source, so nothing in the project starts by itself.
An Actor, Configuration or Model above a placed module keeps its class, so
IsA and FindFirstAncestorOfClass work as they do in your game. Other
containers above one, such as a Script or a Part, become Folders. Attributes
and properties set in Rojo metadata, such as $attributes or a .meta.json,
are left out, and a module runs in the runner’s context, not its Actor’s. To
keep metadata or Actor context, use data-model = "edit".
The test place keeps three names for Luau Run: ServerStorage._LuauRun,
ServerScriptService.TestBootstrap and Workspace.Baseplate. A spec that
reaches a module under one of them is refused, and data-model = "edit" runs
it.
These forms are followed:
game,script,workspaceand a service name.Name,["Name"]and.Parentgame:GetService("X"),:WaitForChild("X")and:FindFirstChild("X")- locals set to such a path above the require
:: Tcasts
Anything else is refused before Studio starts, naming the file and the require:
- a computed name
FindFirstChildwith a second argument- a local that is assigned again on a line of its own
- a path the project does not mount
- two children of one name
- something that is not a ModuleScript
Luau Run also refuses:
- a mounted folder that does not exist, usually packages that are not installed
- two files Rojo gives one name, such as
Thing.luabesideThing.luau - a module under a service the test place does not build, such as
Players
Rojo 7.6 cannot write a sourcemap for a project that mounts a path outside its own folder. 7.7.0 can.
Two kinds of require in a module a spec reaches are listed on standard error instead of refused, since they usually do not run:
- a computed require, such as a lazy
require(ModulePath)inside a function - a Lune or Lute builtin, such as
local task = task or require("@lune/task")
What they would load is not in the test place, so one that does run fails with
an error that names it. In a spec itself, or without rojo-project, both are
refused.
Locals are followed without scopes, from the nearest local Name = line above
the require, so a local hidden by a function parameter can be misread. That can
leave a module out of the test place, but never loads a different one: the
module fails to load with an error that names it.
Aliased requires
Section titled “Aliased requires”An aliased require such as @pkg/Thing is found as Lute finds it: through the
nearest .luaurc that declares the alias, from the module’s folder up to the
project’s folder. An init.luau starts from the folder above its own. A
.config.luau the search reaches is refused, since Luau Run does not run
configuration code.
@std and @lute are always Lute’s own modules, whatever a .luaurc
declares, so they count as builtins like @lune/task.
Lute skips the .luaurc in a folder that has a module of the same name beside
it, such as Thing/ beside Thing.luau. If that .luaurc declares the alias
a require needs, the require is refused. Rename the folder or the module.
Your editor can see aliases differently. luau-lsp merges every .luaurc above
a module and keeps what it read before an error. Lute and Luau Run use only the
nearest one that declares the alias, and stop at an error.
JSON and TOML modules
Section titled “JSON and TOML modules”A .json, .jsonc or .toml file the Rojo project mounts is built as Rojo
builds it: a ModuleScript that returns the file’s table, reached by instance
path or by string require. JSON is read as Rojo 7.6.1 and later read it, with
comments, single quotes, bare keys, and trailing or missing commas. Rojo needs
7.4.0 or later for TOML modules, and 7.7.0 or later for .jsonc.
run-server refuses these:
- a module built from YAML, a model file (
.model.json,.rbxm,.rbxmx) or a project’s ownsyncRules - a TOML file with an offset date and time, an integer of 2^53 or more, or a
date or time Rojo accepts and Luau Run does not, such as
2023-02-31 - a JSON or TOML file the Rojo project does not mount, or any data file without
rojo-project - a ModuleScript with no file of its own: inline in the project file, inside a model file, or made by a meta file
- a module whose
.meta.jsonor.meta.jsoncsetsproperties.Source, or whose node in a project file sets$properties.Source, since Rojo builds that Source instead of the file’s
Each refusal points to data-model = "edit" with rojo-project set, where
Rojo builds the whole place. A Luau file and a mounted data file of the same
name are refused as two modules.
Your project’s Jest globals
Section titled “Your project’s Jest globals”Specs usually load Jest from the project’s own packages, for example
require(ReplicatedStorage.Packages["jest_globals"]). On this lane that
require returns Jest-Portable’s globals instead of loading the project’s copy.
Jest Roblox does the same for any module named JestGlobals. The run says so
once on standard error. Recognising the module needs rojo-project.
[test.jest-portable]project-jest-globals = "replace"project-jest-globals-file = "roblox_packages/jest_globals.luau"project-jest-globals is "replace" (the default) or "keep", which loads the
project’s module like any other. Without project-jest-globals-file,
"replace" recognises a module named JestGlobals, or jest-globals inside a
jsdotlua_jest-globals@ package folder. With it, only that file is replaced,
so a project whose own module is called JestGlobals keeps it. Both settings
apply to the Studio lane only.
© 2026 PRMS Developer