Diagnostics
Every error and warning Rogen reports, with its cause and fix
Updated
Every problem Rogen reports is a diagnostic with a stable code, such as route.strayAt. This page has a section for each code. A section says what causes the diagnostic, shows an example, and says how to fix it.
In a terminal, a diagnostic reads file:line:col - severity: message (code). The line and column appear when Rogen knows them. The examples on this page start at the severity.
- An error stops Rogen from writing the project file.
- A warning never stops the write, but it always names something to fix.
To read a code's section offline, run rogen help <code>. It prints the section from the version you have installed. With --json, each diagnostic has a url that points at its section on this page. Some warnings also carry fixes: the renames or commands that resolve them.
Each diagnostic is about one file, the one to fix. --json and rogen check report one diagnostic for each file. When a warning fires for several files, the commands that print a build show it as one block under the config, with a line for each file, up to ten. Those commands are write, build, serve, sourcemap, upload and syncback.
Config
These diagnostics come from reading a .rogen.json, or a Rojo project file you name.
config.unreadable
Error. Rogen can't read the config. Either the file doesn't exist, or it exists and the read failed. The message says where Rogen looked, or why the read failed.
error: the config does not exist (looked for default.rogen.json). (config.unreadable)
error: the config could not be read: permission denied. (config.unreadable)Fix the path or the file's permissions. Check that the path names a file, not a folder.
config.invalidSyntax
Error. The config isn't valid JSONC. Comments and trailing commas are allowed, but brackets and quotes must match.
error: invalid JSONC: expected '}'. (config.invalidSyntax)Fix the syntax at the line and column that the message shows.
config.notAnObject
Error. The config holds a JSON value that isn't an object, such as an array or a string.
error: a config must be a JSON object. (config.notAnObject)Wrap the fields in { }.
config.wrongType
Error. A field holds the wrong type of value, such as a string where sourcePaths needs an array.
error: "sourcePaths": expected an array, found a string. (config.wrongType)Give the field the type that the message names.
null is never a valid value in a .rogen.json, and it doesn't remove anything. To remove a key, leave it out. To keep a mounted folder out of the project, list it in globIgnorePaths. A node of the tree must be an object, so "DevPackages": null in the tree gets this error too.
config.unknownField
Error. The config has a key that is neither one of Rojo's nor one of Rogen's. It is often a typo, or a key from Rogen 1. Rojo refuses a project file with a key it doesn't know, so Rogen leaves the project file as it was.
error: "sourcePath" is not a Rojo key and not Rogen's, and Rojo rejects a project file with a key it doesn't know. Did you mean "sourcePaths"? (config.unknownField)Rename the key to the one that the message suggests, or remove it.
The message suggests a key only when one of Rojo's or Rogen's keys is close. A $ key of a node in the tree gets this error too when it isn't one of Rojo's fields, such as $clasName. The exception is a $ key whose value is an object, because Rojo reads that as a child. An unknown field in a sync rule gets this code as a warning instead. Rojo ignores that field, so the rule doesn't do what it seems to say. A config with Rogen 1 keys also gets legacy.config.
config.duplicateSourcePath
Error. One folder appears twice in sourcePaths, so every file in it would belong to both entries.
error: source path "src" is listed twice; a file under it would belong to both. Remove one. (config.duplicateSourcePath)Remove one of the entries.
config.nestedSourcePath
Error. One source path is inside another, so the files in it would belong to both.
error: source path "src/shared" is inside source path "src"; a file under it would belong to both. Remove one. (config.nestedSourcePath)Remove the inner source path, or move its folder out of the outer one.
config.identicalConfig
Error. Two configs in one folder are the same except for their file names. They have the same name, source paths, routes, tree and every other key. One of them is a copy that was never edited, and Studio would list two projects with one name that read the same code. Both configs report the error.
error: game.rogen.json and lobby.rogen.json are the same config: a copy that was not edited. Change "name", "sourcePaths" and what else the copy is for, or delete it. (config.identicalConfig)Edit the copy so it describes the place or output it is for, or delete it. A second output of one game, such as dist or release, keeps the same name and changes only what differs.
config.compiledPathOverlapsSourcePath
Error. The compiled path is a source path, is inside one, or contains one. Darklua or a compiler writes its output to the compiled path, so Rogen would read that output as source and write the project file from it.
error: the compiled path "src/out" is inside source path "src", so Rogen would read what the tools write as source. Set "compiledPath" to a folder outside the source paths. (config.compiledPathOverlapsSourcePath)Set compiledPath to a folder beside the source paths, such as dist or out.
config.sourcePathsWithoutRoutes
Error. The config lists sourcePaths but declares no routes. Rogen scans source paths only to route their files, so without routes it routes nothing and scans no source path.
error: "sourcePaths" lists what routes scan, but the config declares no routes. Add "routes", or remove "sourcePaths". (config.sourcePathsWithoutRoutes)Add a routes map. Or remove sourcePaths, and mount the folders in the tree with $path. rogen init writes the routes Server, Client, Shared and *. See Routing.
config.invalidSyncRule
Error. A rule in syncRules isn't one that Rojo can read. One of these is true:
- The rule isn't an object.
- The rule has no
patternor nouse. - The rule's
useisn't one that Rojo has. - The rule's
excludeorsuffixisn't a string.
error: "syncRules[0]": a sync rule needs a "use" of serverScript, clientScript, ... (config.invalidSyncRule)Fix the rule as the message says.
config.invalidRouteKey
Error. A route key has a character that isn't a letter or a digit, or it starts with a digit. Keys appear in folder and file names, so they must match exactly.
error: route key "ser-ver" is invalid: use letters and digits only, starting with a letter. (config.invalidRouteKey)Rename the key, for example to server. See Routing.
config.ambiguousKey
Error. Two declared keys differ only in the case of their first letter. A name matches a key whose first letter is in either case, so both keys would match the same folders.
error: "Server" and "server" differ only in the case of their first letter, so both would match the same names; keep one of them. (config.ambiguousKey)Keep one of the keys. See How Routing Works.
config.unnamedProjectFile
Error. A Rojo project file that you named on the command line has no name, as in rogen serve test.project.json. Rojo names default.project.json after its folder. It crashes on a project file with any other file name and no name, so Rogen stops before Rojo does.
error: test.project.json has no "name", and Rojo can't read a project file without one unless it is default.project.json or default.project.jsonc. Add "name". (config.unnamedProjectFile)Add a "name" to the file.
Routes
These diagnostics come from route targets, and from how file and folder names match route keys.
roblox.unsupportedService
Error. A route's target doesn't start with a Roblox service that Rojo can write to.
error: "StarterPlayerScripts" is not a supported service. Did you mean "StarterPlayer/StarterPlayerScripts"? (roblox.unsupportedService)Start the target with a service, then any folders, such as "StarterPlayer/StarterPlayerScripts" or "ReplicatedStorage/Shared". See Targets.
roblox.invalidFolder
Error. A route's target has a folder whose name is empty, . or ... Rojo would make an instance with that name.
error: the target "ServerScriptService/" has an empty folder name; write each folder between single slashes, such as "ServerScriptService/Folder". (roblox.invalidFolder)Remove the extra slash, or name the folder. See Targets.
route.unrouted
Warning. No route matches the file, and the config has no * route, so Rogen leaves the file out of the project file.
warning: matched no route, so it is left out. Move it into src/Shop/Server, Client or Shared, end its name with a route's @ marker (@Server, @Client or @Shared), or declare a "*" route. (route.unrouted)Do one of these:
- Move the file into one of the routing folders that the message names.
- Add an
@keysuffix to the file's name. - Declare a
"*"route, if every file like this one belongs in one place.
The message names the routing folders of the file's feature. The feature is the folder directly inside the source path that holds the file. For a file at the top of a source path, the feature is the source path. See Files Without a Route.
route.strayAt
Warning. A name, folder or marker file has an @ that doesn't route, so the @ stays in the instance name. This happens in two cases:
- The text after the
@nearly spells a declared route key, with a typo or the wrong letter case. - The text spells a route key, but it isn't at the end of the name, as in
Report@server.bak.luau.
warning: 2 names have an "@" that routes nowhere, so they are read as ordinary names: (route.strayAt)
src/Inventory/Load@SERVER.luau (did you mean "@server"?)
src/Inventory/Report@server.bak.luau ("@server" must end the name)Rename the file to the spelling that the message suggests, or move the @key to the end of the name. In --json, fixes holds the rename when exactly one key is closest.
Rogen doesn't report an @ that is nowhere near a route key, such as the @ in a package name like @rbxts. See The @ Suffix.
route.dotRoute
Warning. A name has a route key after a dot, where only @ routes, so the key routes nothing. The name is one of these:
- a dot-file such as
.server, which isn't a marker file - a dot-folder such as
.server/, which isn't a routing folder - a name with a dot part, such as
Types.shared.luauorNet.server/, which stays in the name
What the name covers falls through to the route above it, or to *. The key matches in any letter case, so .SERVER/ and Types.SHARED.luau warn too.
warning: 2 names write a route key after a dot, where only "@" routes, so they route nothing: (route.dotRoute)
src/Inventory/.server (write "@server")
src/Inventory/Types.shared.luau (write "Types@shared.luau")Rename each one to its @ form. A marker file becomes @server, a folder becomes @server/, and a name becomes Types@shared.luau or Config@server.json. In --json, fixes holds the rename.
A name inside a folder that a route already governs gets no rename, because @server there would be a route.ignoredAt error. Its message says which route governs it, and tells you to move it out of that route's files.
Rojo's .server and .client at the end of a script's name still route, and Rogen never reports them. Two limits apply:
- Only lowercase counts. Rojo reads
Boot.Server.luauas a ModuleScript namedBoot.Server, so Rogen suggestsBoot.server.luau. - Only scripts count. A data file or a model has no
.serveror.clienthandling, soConfig.server.jsonis a ModuleScript namedConfig.server, and it warns.
See Marker Files.
route.folderTypo
Warning. A folder's name is one edit away from a declared route key, such as Sever/ when Server is a key. Rogen reads it as an ordinary folder, so its files fall through to the route above it, or to *.
warning: 1 folder is one edit from a declared route key, so it is read as an ordinary folder: (route.folderTypo)
src/Inventory/Sever (did you mean "Server"?)
Rename a folder to the route key if it should route; a folder named as it is stays an ordinary folder.Rename the folder to the key that the message suggests. If the typo is in your config, fix the key in routes instead. In --json, fixes holds the rename when exactly one key is closest.
One edit is one letter added, removed or changed, or two neighbouring letters swapped, as in Sevrer/. A plural counts too. Servers/ is an ordinary folder, so it warns. Rename it if its files belong under the route. Rogen compares the name without its parentheses and its ^. It matches only keys of four letters or more, because shorter keys are one edit from real words. A name that matches a key in a different letter case gets route.caseMismatch instead.
route.markerClash
Error. Two marker files in one folder name different routes, such as @server beside @client. Both are at the same level, so nothing decides which one governs.
error: "@client" and "@server" route this folder to different places, and nothing decides between them. Keep one. (route.markerClash)Delete the marker that you don't want. Or move part of the folder into a subfolder with its own marker.
An init script's route suffix counts as a marker, so @server beside init@client.luau clashes too. Two markers for the same route are fine. See Marker Files.
route.ignoredAt
Error. A name or marker file has an @key that does nothing, so the name says the file goes somewhere that it doesn't. This happens in two cases:
- The file is inside a folder that another route already governs. Only the outermost route acts.
- The
@keycomes before another@keyin the same name, as inNet@client@server/. Only the last@keyin a name routes.
error: "@client" does nothing here, because the "server" route already governs this file. Remove it, or move the file out of the "server" route's files. (route.ignoredAt)Remove the @key, or move the file out of the governing route's folder. Rogen offers no automatic fix, because the right choice depends on where the code should run.
An @ that restates the governing route is fine, as in Shared/Net/Remote@shared.luau. Rogen also reports a file that another file replaces, because its name is wrong either way. See The Outermost Route Wins.
route.caseMismatch
Warning. A folder or marker file matches a declared key except for the letter case after the first letter. Rogen reads it as an ordinary name.
warning: differs from the route "shared" only in letter case, so it is read as an ordinary name. Spell it "shared" or "Shared", or declare it as written. (route.caseMismatch)Rename it to the key. If it should route as it is written, declare that spelling as a key. Rogen offers no automatic fix, because a name like SHARED/ can be an ordinary folder on purpose. See How Routing Works.
route.serverCodeShipped
Warning. A file is in a plain folder named after a server route, such as Server/ or (Server)/, but an outer route outranks that folder. The outer route places the file, and that route replicates to clients. Server code under Shared/ ships to every client.
warning: ships to clients as ReplicatedStorage/Shared/Datastore: move it out of the "Shared" route's files if it's server code, or keep it there with a "@Shared" marker file in its folder (route.serverCodeShipped)Move the file out of the replicating route's folder, for example from Shared/Server/ to Server/.
If the folder should replicate, put a marker file in it that restates the governing route, such as Shared/Server/@shared. The marker covers every file below it. To cover one file, name it like Secret@shared.luau.
A route written with @, as in Shared/Data@server.luau, gets the route.ignoredAt error instead. See The Outermost Route Wins.
Tree
These diagnostics come from the instance tree that Rogen writes: clashes between files and nodes, mounts, and scripts that land where they don't run.
tree.reservedName
Warning. The project file gets an instance whose name starts with $, which Rojo reserves for its own fields. Rojo keeps the instance, but it warns about it on every build and every serve.
warning: the project file gets the instance "ReplicatedStorage/shared/$Config", and Rojo reserves a leading $ for its own fields, so it warns of it on every build. Rename the file without the $. (tree.reservedName)Rename the file or folder without the $.
A $ later in a name, as in Cost$, is fine. So is a file inside a folder that Rogen gives to Rojo whole, as one $path.
tree.instanceClash
Warning. Two files in one source path become the same instance, such as Types.lua and Types.luau. The last one takes the instance, and Rogen leaves the other out.
warning: becomes "ReplicatedStorage/shared/Inventory/Types", as src/Inventory/Types.luau does, which takes its place. Rename one of them to keep both. (tree.instanceClash)Rename or delete one of the files. In --json, related names the file that takes the instance. rogen where shows the left-out file as replaced by.
Across source paths, the last file wins without a warning. That is how a later source path replaces a file of an earlier one.
tree.nodeClash
Warning. The tree defines a node at the same instance path as a file or folder. Rogen keeps the tree's node and leaves the file out.
warning: the tree defines "ServerScriptService/Save" too, so its node is kept and this file is left out. Rename one of them to keep both. (tree.nodeClash)Rename the file, or remove the node from the tree.
tree.mountClash
Warning. A route puts files at or below a node of the tree that has a $path, and the mounted folder holds an instance with the same name. Rojo reads the mount itself and adds the routed files beside what the mount holds. The game gets two instances with one name, and require can find either one.
warning: 2 files sit next to an instance of the same name that a mount of the tree holds, so Rojo builds two of each: (tree.mountClash)
src/Combat/Hit.luau (makes a "Combat" next to the "Combat" that the mount of vendor/Lib at "ReplicatedStorage/Lib" holds)
src/Combat/Miss.luau (makes a "Combat" next to the "Combat" that the mount of vendor/Lib at "ReplicatedStorage/Lib" holds)
Rename one of each pair, or route outside the mounted folder.Rename one of each pair, or route the files somewhere that the mount doesn't cover.
rogen where shows the warning under each file. Files that the config ignores in the mounted folder don't count.
tree.initWithoutFolder
Error. An init script becomes the folder it is in, but that folder never becomes an instance. Source paths, plain routing folders and invisible folders never become instances.
error: an init script becomes the folder it sits in, but it sits in a routing folder, which never becomes an instance. Move it into a folder of its own, or rename it. (tree.initWithoutFolder)Move the script into a folder of its own, or rename it so it isn't an init script.
tree.hoistedInit
Error. An init script's name starts with ^, but an init script can't be hoisted alone. The script is its folder, so only the folder can be hoisted.
error: ^init.luau starts with "^", but an init script is its folder, so the "^" can't hoist it alone. Put the "^" on the folder: ^Net. (tree.hoistedInit)Rename the script back to init.luau, and rename the folder to ^Net. See Hoisted Names.
tree.deadScript
Warning. A Script or LocalScript lands in a service where Roblox never runs it, such as a LocalScript in ServerScriptService.
warning: 1 script will never run where it lands: (tree.deadScript)
src/Shared/Secret.server.luau (a Script never runs in ReplicatedStorage)
A Script runs in ServerScriptService or Workspace, and a LocalScript in StarterPlayerScripts, StarterCharacterScripts, StarterGui, StarterPack or ReplicatedFirst. A Script with RunContext Client never runs in ServerScriptService, which clients can't see.Move the script under a route whose target runs it. Or remove .server or .client from its name to make it a ModuleScript.
tree.runContextTarget
Warning. The config sets emitLegacyScripts: false, and a route puts an init.client script in StarterPlayerScripts or StarterCharacterScripts. Rogen keeps the other .client scripts there as LocalScripts, with a sync rule for each. Rojo reads init scripts without sync rules, so this one becomes a Script with RunContext Client.
warning: emitLegacyScripts: false makes an init script in StarterPlayerScripts or StarterCharacterScripts a Script with RunContext Client, because Rojo reads init scripts without sync rules: (tree.runContextTarget)
src/Panel/init.client.luau (an init script that sync rules can't keep a LocalScript)
Route the folder to another service, or remove emitLegacyScripts from the config.Route the folder to a service where a Script with RunContext Client runs, such as ReplicatedStorage. Or remove emitLegacyScripts from default.rogen.json.
Rogen skips a script whose meta sets RunContext. That script gets no sync rule, because its meta decides how it runs.
tree.mountsSourcePath
Error. A $path in the tree mounts a source path, or a folder that holds one. Rojo would read the whole folder, and Rogen could place nothing in it.
error: "ReplicatedStorage/All" mounts the source path src, so Rojo would read all of it and Rogen would place nothing there. Mount a folder inside the source path, or remove the source path from "sourcePaths". (tree.mountsSourcePath)Mount a folder inside the source path instead, such as a vendored package. Or remove the source path from sourcePaths.
tree.rootNotDataModel
Error. The config declares routes, but the root of its tree isn't a DataModel. Route targets name services, and only a DataModel holds services. A root with a $path and no $className isn't a DataModel either.
error: routes name services, but the root of the tree is a Folder, not a DataModel. Give it "$className": "DataModel", or remove the routes. (tree.rootNotDataModel)Give the root "$className": "DataModel". If the project is a model, remove the routes instead. Without routes, any root is valid.
Metadata
These diagnostics come from .meta.json files. Rogen reads a folder's init.meta.json itself, and checks other meta files before Rojo reads them.
meta.unreadable
Error. Rogen found a .meta.json file when it scanned, but it couldn't read the file. The file has the wrong permissions, is a folder, or was removed while the write ran.
error: the meta file could not be read: permission denied. (meta.unreadable)
error: the meta file does not exist any more; it was there when the write scanned and was removed while it ran. (meta.unreadable)Fix the file's permissions, or run the write again.
meta.invalidSyntax
Error. A folder's init.meta.json isn't valid JSONC.
error: invalid JSONC: expected '}'. (meta.invalidSyntax)Fix the syntax at the line and column that the message shows.
Rogen reads a folder's meta because it merges that meta into the project file. Rojo reads the meta of a single file itself, and reports that file's errors.
meta.byteOrderMark
Error. A meta file starts with a byte order mark, which Rojo can't read. A byte order mark is an invisible character that some editors, and PowerShell's Out-File, write at the start of a UTF-8 file. Rojo refuses the whole project when a meta file starts with one. Rogen stops before it writes a project file that Rojo would fail on.
error: starts with a byte order mark, which Rojo can't read, so it refuses the project. Save the file as UTF-8 without one. (meta.byteOrderMark)Save the file as UTF-8 without a byte order mark.
meta.notAnObject
Error. A folder's init.meta.json holds a JSON value that isn't an object.
error: a meta file must be a JSON object. (meta.notAnObject)Wrap the fields in { }.
meta.wrongType
Error. A field in a folder's init.meta.json holds the wrong type of value.
error: "attributes": expected an object, found an array. (meta.wrongType)Give the field the type that the message names. It is the type that Rojo's meta format expects.
meta.unreadableValue
Error. A value in a meta file's properties or attributes is one that Rojo can't read, such as null, a list of numbers of the wrong length, or an object with several keys. Rojo refuses the meta. Without this check, the build fails later, with a message that doesn't name the file.
error: "properties.WorldPivotData": Rojo can't read this value, so it refuses this meta. Write a boolean, a number, a string, a list of numbers (2, 3, 4 or 12), a list of strings, or a { "Type": value } pair. (meta.unreadableValue)Write a value that Rojo can read, or remove the property.
meta.unknownField
Warning. A meta file has a field that looks like a misspelling of one that Rojo reads, such as classname for className in an init.meta.json. Rojo ignores an unknown field without a warning, so the property never applies.
warning: unknown field "classname"; Rojo ignores it. Did you mean "className"? (meta.unknownField)Rename the field to the one that the message suggests, or remove it.
Rogen doesn't report a field that resembles none of Rojo's, such as $schema.
meta.unclaimed
Warning. A .meta.json file belongs to no file, so Rojo ignores it. A file's meta is named after the name that Rojo gives the file, which drops .server, .client and .plugin.
warning: belongs to no file, so Rojo ignores it. Rojo reads Save.meta.json. (meta.unclaimed)Rename the meta file to the name that the message gives, or delete it. A folder's meta is init.meta.json, inside the folder.
meta.appliesToNothing
Warning. An init.meta.json is in a folder that never becomes an instance, such as a routing folder or an invisible folder.
warning: applies to nothing, because a routing folder never becomes an instance. Move the meta into the folder that should get it. (meta.appliesToNothing)Move the meta file into the feature folder that should get it.
meta.sharedWithScript
Warning. A folder and a script become the same instance, and the folder has an init.meta.json. Rojo reads the script at that instance, so the folder's meta applies to nothing.
warning: this folder shares "ServerScriptService/Net" with Net.server.luau, which is what Rojo reads there, so its meta applies to nothing. Put it in Net.meta.json beside the script, or turn the folder into an init folder. (meta.sharedWithScript)Put the fields in the script's own meta file, as the message names. Or make the folder an init folder.
meta.treePath
Warning. The tree gives the folder's instance its own $path, so Rogen can't copy the folder's meta to it.
warning: the tree gives "ServerScriptService/Combat" its own $path, so this meta isn't copied there. Set the fields on the tree's node instead. (meta.treePath)Set $className, $properties or $attributes on the tree's node instead.
meta.treeClass
Warning. The tree and a folder's meta give one instance different classes. The tree's class wins.
warning: the tree makes "ServerScriptService/Combat" a Model, so its class is kept over this meta's Actor. (meta.treeClass)Remove $className from the tree's node, or remove className from the meta.
meta.sameNode
Error. Two folders in one source path become the same instance, and both have an init.meta.json. An example is src/Combat/ and src/server/Combat/. Neither meta file ranks above the other.
error: src/Combat/init.meta.json and src/server/Combat/init.meta.json both apply to "ServerScriptService/Combat" from one source path, and neither ranks above the other. Keep one of them. (meta.sameNode)Merge the two into one meta file.
meta.idOnSeveralNodes
Error. A folder's meta sets an id, but the folder's files are split across services. Rogen would copy the meta onto several instances, and a Rojo ref id must be unique.
error: id "combat" would be copied onto 2 instances (ServerScriptService/Combat, ReplicatedStorage/Combat), but a ref must be unique. Remove the id, or keep the folder's files in one service. (meta.idOnSeveralNodes)Remove the id, or keep the folder's files in one service.
meta.runContextOnModule
Error. A meta file sets RunContext on a ModuleScript. A ModuleScript has no RunContext, so Rojo refuses the meta.
error: sets a RunContext, but init.luau is a ModuleScript, which has none, so Rojo refuses this meta. Name the script .server or .client to make it a Script, or remove RunContext. (meta.runContextOnModule)Add .server or .client to the script's name to make it a Script, or remove RunContext. See Rojo's Script Suffixes.
meta.classNameOnScript
Error. A folder's init.meta.json sets className, but the folder holds an init script. The script is the folder's instance and decides its class, so Rojo refuses the meta. init.luau is a ModuleScript, init.server.luau is a Script, and init.client.luau is a LocalScript.
error: sets a className, but its folder holds an init script, which decides the class, so Rojo refuses this meta. Remove className, or rename the script to change its class. (meta.classNameOnScript)Remove className, or rename the init script to make the class you want.
Scanning
These diagnostics come from reading the source paths: folders that are missing, names that Rojo or another system can't use, and files in places Rogen doesn't expect.
scan.missingSourcePath
Warning, or error. A folder in sourcePaths doesn't exist, or is a file.
- It is a warning while another source path is a folder. The missing one contributes nothing.
- It is an error when no source path is a folder, because the build would write an empty tree over your project file.
rogen write,rogen buildandrogen checkfail, and the project file stays as it was.
warning: this source path does not exist or is not a folder, so it contributes nothing. (scan.missingSourcePath)error: this source path does not exist or is not a folder, and no other source path of the config does, so there is nothing to write. default.project.json was left as it was. Check the spelling in "sourcePaths". (scan.missingSourcePath)Create the folder, fix the spelling, or remove the path from sourcePaths. Each path is relative to the .rogen.json that lists it.
A config with no sourcePaths uses the default, src. The error then tells you to create src, or to set sourcePaths to where your code is. A running rogen write --watch, rogen build --watch or rogen serve keeps the last good project file, and builds again when a source path is back.
scan.unmountedSource
Warning. The default src folder holds files that Rojo never syncs. The config declares no routes, so Rogen scans no source path, and nothing in the tree mounts the files.
warning: 3 files here are mounted by nothing in the tree, and the config declares no routes, so Rojo never syncs them. Add "routes" to place them, or mount the folder with "$path". (scan.unmountedSource)Add routes so that Rogen places the files. Or mount the folder in the tree with a $path.
Files that globIgnorePaths matches don't count.
scan.extensionCase
Warning. A file's extension has capital letters, so Rojo ignores the file. Rojo reads an extension only in lowercase. Rogen leaves the file out of the tree, as Rojo does.
warning: Rojo reads an extension only in lowercase, so it ignores this file. Rename it to Save.luau. (scan.extensionCase)Rename the file as the message says. This applies to .JSON, .MODEL.JSON and every other extension that Rojo reads.
scan.syncRuleSuffix
Warning. A sync rule takes a file, but the rule's suffix doesn't end the file's name. Rojo removes the suffix from a file's name to name the instance. When there is no suffix to remove, Rojo keeps the whole file name, extension included.
warning: the sync rule "*.md" cuts ".txt" off a file name, but this name does not end with it, so Rojo names the instance after the whole file name. Make the suffix end every file the pattern matches. (scan.syncRuleSuffix)Change the suffix or the pattern, so that the suffix ends every file that the pattern takes.
scan.nestedProject
Warning. A default.project.json or default.project.jsonc is directly in a source path, not in a folder below it. Rojo reads such a file as the folder it is in. A source path never becomes an instance, so Rogen places the project on its own. The project is named by its name, or default if it has none.
warning: Rojo reads a default.project.json as the folder it lies in, but a source path never becomes an instance, so this project becomes ReplicatedStorage/Shared/Arena on its own. Move it into a folder of its own. (scan.nestedProject)Move the file into a folder of its own, or out of the source paths.
In a folder below the source path, the project file is that folder, as it is in Rojo. The folder becomes one instance, named by the project's name, and Rojo reads only what the project mounts.
scan.sourcePathNamedAfterKey
Warning. A source path is named after a route key, but its name routes nothing. Routing starts below a source path, so its files land where the * route sends them, or nowhere.
warning: 2 source paths are named after a route key, but routing starts below a source path, so their names route nothing: (scan.sourcePathNamedAfterKey)
server (named after the "server" route: move it into a folder, such as src/server, and use "sourcePaths": ["src"])
client (named after the "client" route: move it into a folder, such as src/client, and use "sourcePaths": ["src"])If the source path has a parent folder inside the project, such as src/server, list the parent instead: "sourcePaths": ["src"]. The server folder then routes. If the source path is in the same folder as the .rogen.json, first move the folders into one code folder, because "." would scan the whole repository. See Routing.
The build still runs and writes the project file.
scan.unresolvedLink
Warning. A symlink or junction in a source path points at nothing, or back at a folder that contains it.
warning: this link points at nothing, or back at a directory that contains it, so it contributes nothing. (scan.unresolvedLink)Fix the link's target, or remove the link.
scan.emptyName
Warning. A script file's name is only its suffix, such as .server.luau, so it becomes an instance with an empty name. Rojo builds it the same way. Studio and require don't handle an empty name well.
warning: has no name once its suffix is taken off, so it becomes an instance with an empty name. Put a name before the suffix, as in Name.server.luau. (scan.emptyName)Put a name before the suffix.
scan.outsideSourcePaths
Warning. rogen check <path> got a path that is in no source path, and the path's first folder is one edit from a source path, or differs from one only in letter case. The path is probably a typo.
warning: this path is in no source path, so Rogen leaves it out of the project file, and "scr" is one edit from the source path "src". Check the spelling. (scan.outsideSourcePaths)Fix the path. If the typo is in sourcePaths, fix it there.
Any other path outside the source paths passes without a warning, because hooks give check every changed file.
scan.portableName
Warning. A file or folder name works on this machine, but fails on Windows or macOS, or Rogen can't read it. A name fails when it does one of these:
- has one of
<>:"|?*or a control character - is a Windows device name (
con,prn,aux,nul,com1tocom9, orlpt1tolpt9), with any extension - ends in a space or a dot
- differs from a sibling only in letter case
warning: its name has ":", which Windows file names cannot hold. Rename it so a checkout works on every system. (scan.portableName)Rename the file or folder, and update what requires it.
Rogen leaves nothing out, except a file whose name has a backslash. Rogen reads \ as a folder separator, so it leaves that file out. The check covers each file and folder that becomes an instance, and meta files and marker files. It skips files that Rogen ignores.
Output
These diagnostics come from writing the project file, and from reading a compiler's output in compiledPath.
output.writeFailed
Error. Rogen couldn't write the project file. The message gives the reason, without the system's error code.
error: the project file could not be written: permission denied. (output.writeFailed)Check that the folder is writable, and that no other program locks the file. Rogen creates the folder if it is missing.
output.differs
Warning. rogen check found a project file on disk that differs from what rogen write would write now, so the file is stale. Without paths, check compares the project file of every config in the folder. With paths, it compares the project files of the configs that those paths belong to. check writes nothing.
warning: this file differs from what 'rogen write' would write: its sources changed since it was written. Run 'rogen write' to write it again; what it holds comes from default.rogen.json, so change that to change it. (output.differs)Run rogen write. For a project other than default, run rogen write <project>. In --json, the diagnostic carries the command as a run fix. If git tracks the project file, commit the result. If git ignores it, a stale copy does no harm.
Rogen doesn't report a project file that doesn't exist yet.
output.nothingEmitted
Warning. The config has a compiledPath, but the compiled path holds nothing that the compiler or processor should have written for a source path. Rojo would find nothing to sync.
If the compiled path doesn't exist, as before the compiler or processor first runs, there is one warning for the config, however many source paths it has:
warning: the compiled path "out" doesn't exist yet, so Rojo has nothing to sync. Run your compiler or processor first. (output.nothingEmitted)If the compiled path exists but a source path's part of it is missing, or holds only the placeholders Rogen creates for Rojo, the warning names that source path and the nearest path that exists. If the output is there but rooted one level off, the warning says where it found the output:
warning: nothing emitted for source path "src" exists under "out/src". The nearest path that exists is "out" — has your compiler or processor run? (output.nothingEmitted)
warning: nothing emitted for source path "core" exists under "out/core". Found "out/Types.luau" — is the output of your compiler or processor rooted differently? (output.nothingEmitted)Run the compiler or processor first. If the message found the files somewhere else, point compiledPath at the folder that mirrors the source paths.
output.metaNotSynced
Warning. Some .meta.json files have no copy in the compiled path, so Rojo doesn't apply them. Either the compiler didn't copy them, or a processor converted them. Darklua turns them into .meta.lua, which Rojo reads as a ModuleScript.
warning: 1 meta file has no copy under "dist" (src/Inventory/Save.meta.json), so Rojo doesn't apply it. The processor turned it into .meta.lua, which Rojo syncs as a ModuleScript instead of applying. Darklua converts every .meta.json this way. (output.metaNotSynced)After the compiler or processor runs, copy the .meta.json files unchanged into the compiled path.
output.dataFileConverted
Warning. A processor turned data files, such as .json or .txt files, into Lua modules in the compiled path. Rojo doesn't find them at the path that the write expects.
warning: 1 data file was turned into a Lua module under "dist" (src/Inventory/Rates.json: expected "dist/Inventory/Rates.json", found "dist/Inventory/Rates.lua"). Rojo finds nothing at the path the write expects, or a ModuleScript where a folder collapses. Darklua converts .txt, .json, .toml, .yaml and .yml files this way, and has no option to copy them. Copy the data files unchanged into the compiled path after it runs, or require them as modules. (output.dataFileConverted)After the processor runs, copy the data files unchanged into the compiled path. Or require them as modules.
compiled.orphan
Warning. The compiled path holds a file that no source file makes. A compiler or processor doesn't delete what it wrote on an earlier run, so a file whose source you removed or renamed stays there. Rogen gives one warning for each folder, and lists the first few files:
warning: dist/Inventory/Old.luau is in the compiled path and no source file makes it, so Rojo may still sync it. Delete it, or compile again from a clean folder. (compiled.orphan)Delete the file. Or empty the compiled path, and run the compiler or processor again.
Where a folder collapses into one $path, Rojo syncs every file in it, including the stale one. In a folder that doesn't collapse, Rojo skips the stale file, but the file stays on disk.
Rogen matches a file to its source by the name a tool gives it. roblox-ts compiles .ts and .tsx to .luau, and index.ts to init.luau. Darklua turns a data file into .lua. A source that globIgnorePaths leaves out still counts as making its file. When Rogen can't tell, it doesn't warn. rogen check exits 1 on this warning, and build only prints it.
Format
These diagnostics come from rogen fmt-project.
format.commentsLost
Error. rogen fmt-project won't write a config that has comments, because the formatted text has none. It always refuses a .rogen.jsonc, because that file is meant to hold comments. Nothing is written.
error: default.rogen.json has comments, and formatting writes none. Remove them first, or format it in your editor. (format.commentsLost)Remove the comments if you don't need them, or format the file in your editor.
format.writeFailed
Error. rogen fmt-project couldn't write the formatted config. The message gives the reason, without the system's error code.
error: the config could not be written: permission denied. (format.writeFailed)Check that the file is writable, and that no other program locks it.
Init
These diagnostics come from rogen init, which starts projects and lifts a hand-written default.project.json into a config.
init.configExists
Error. The folder already has a .rogen.json or .rogen.jsonc, either default or named. init never overwrites or changes a config, so it stops and writes nothing. With --agent-rules or --agent-hook, init adds only the agent files instead. A flag that shapes a config, such as --language, is then an error.
error: this config already exists, and init never overwrites or changes one. To change it, edit the .rogen.json and run 'rogen check'; for a new place, copy a config and edit the copy. To add the agent rules or the agent hook to this project, run 'rogen init --agent-rules' or 'rogen init --agent-hook'; to set Rojo up, see https://rogen-roblox.vercel.app/docs/v2/installation. (init.configExists)To change the config, edit it and run rogen check. For a new place, copy a config and edit the copy. To add the agent rules or the agent hook later, run rogen init --agent-rules or rogen init --agent-hook. See Working with agents. To set up Rojo, see Installation.
init.fileExists
Error. A file that init would write already exists, such as a roblox-ts tsconfig.json. init never overwrites a file.
error: this file already exists, and init never overwrites one. Pick another name. (init.fileExists)Move the file out of the way.
init.projectUnreadable
Error. init found a hand-written default.project.json to lift into default.rogen.json, but it couldn't read the file, or the file isn't a valid project file.
error: couldn't read this file to lift it: permission denied. Fix the file, or move it away to start a new project. (init.projectUnreadable)
error: this file does not exist, so it can't be lifted. (init.projectUnreadable)Fix the file's permissions or its contents. To start a new project instead, move default.project.json away: init always lifts it when it is there.
init.mountNarrowed
Warning. init lifted a default.project.json with a node that mounts a whole source path, beside nodes that mount folders inside it. Rojo puts those folders in two places. For example, src/server is at ServerScriptService/Server, and also inside the node that mounts src. Rogen turns the folders into routes, and the node that mounts src into the * route. Each folder is then only where its route puts it.
warning: ReplicatedStorage/Common mounted all of src, so Rojo also put src/server inside it. Rogen routes that folder only to ServerScriptService/Server, so a require that reaches it through ReplicatedStorage/Common breaks. Check with 'rogen where src/server'. (init.mountNarrowed)Change each require that reaches a folder through the mounted node, so that it uses the folder's own node.
init.settingsDropped
Warning. init couldn't keep the settings of a node that it lifted from default.project.json. The node mounts a folder of your source, and no route lands on it, so default.rogen.json has no place for its settings. A setting is any of $properties, $attributes, $className, $ignoreUnknownInstances, $id or a child node.
warning: Workspace/Map set $properties, which default.rogen.json doesn't carry, since no route lands on that node. Add them to the tree by hand. (init.settingsDropped)Add the settings to the node in the tree of default.rogen.json.
init keeps the settings of a node that a route lands on.
init.unmountedFiles
Warning. init lifted a default.project.json, and found files in the source paths that none of its nodes mount. Rojo ignored those files. Rogen places every file below a source path that a route matches, so those files join the game. If there is no * route, Rogen leaves out the files that no route matches, with route.unrouted.
warning: 2 files in the source paths are mounted by no node, so Rojo ignored them, and Rogen places each one a route matches: src/Loose.luau and src/scratch/x.server.luau. Check where with 'rogen where <path>', and list them under "globIgnorePaths" to leave them out as Rojo did. (init.unmountedFiles)Run rogen where on the files to see where they land. To keep them out of the game, list them under globIgnorePaths in default.rogen.json, or delete them.
init.codeOutsideSourcePaths
Warning. init found code that no source path holds and that the tree doesn't mount, so Rogen places none of it. Package folders and a compiler's output don't count. With no default.project.json, the source path is src, or the only folder that holds code if no route is named after it. When init lifts a default.project.json, the source path is the closest folder that holds every folder of code that the file mounts. When a route is named after that folder, such as src/server, the source path is its parent, src, if the routes put the code where the file did. If they don't, the tree keeps the mounts.
warning: game and lib hold code that no source path holds and the tree doesn't mount, so Rogen places none of it. Move the code into src, or list its folders under "sourcePaths" in default.rogen.json. (init.codeOutsideSourcePaths)Move the code into a source path, or add its folders to sourcePaths in the config. If the code isn't part of the game, such as a script that a tool runs, you can leave it where it is.
Serve
These diagnostics come from rogen serve and the Rojo server that it starts.
serve.noServer
Error. rogen serve found no Rojo. No rokit.toml, aftman.toml or foreman.toml in the folder or above pins it, and it isn't on the PATH. serve starts only Rojo, so a pinned Argon doesn't count. If Argon is pinned, the message says so.
error: No Rojo to serve with: none is pinned in a toolchain file here or above, or on the PATH. Run 'rokit add rojo-rbx/rojo', then 'rogen plugin install' to install its Studio plugin. To set Rojo up by hand, see https://rogen-roblox.vercel.app/docs/v2/installation. (serve.noServer)
error: No Rojo to serve with: none is pinned in a toolchain file here or above, or on the PATH. Run 'rokit add rojo-rbx/rojo', then 'rogen plugin install' to install its Studio plugin. Argon is pinned, but rogen serve only starts Rojo: run 'rogen write --watch' to keep the project files current, and 'argon serve' to serve them. To set Rojo up by hand, see https://rogen-roblox.vercel.app/docs/v2/installation. (serve.noServer)Pin Rojo with your toolchain manager, then install Rojo's Studio plugin with rogen plugin install:
- Rokit:
rokit add rojo-rbx/rojo - Aftman:
aftman add rojo-rbx/rojo - Foreman: add Rojo to
foreman.tomlby hand, because Foreman has no add command.
Rogen never installs Rojo. In a new project, rogen init writes the pin into your toolchain file, and you run the manager's install. See Installation. To serve with Argon instead, run rogen write --watch and argon serve.
serve.notInstalled
Error. A toolchain file pins Rojo, but Rojo isn't installed, so its command isn't on the PATH.
error: rokit.toml pins Rojo as rojo, but it isn't installed. Run 'rokit install'. (serve.notInstalled)Run the manager's install command: rokit install, aftman install or foreman install.
serve.serverFailed
Error. <tool> --version failed, so Rojo can't start. Rogen runs that command before it writes. The message ends with the first line that Rojo printed.
error: 'rojo --version' failed, so Rojo can't start: Failed to find tool 'rojo' in any project manifest file. If Rojo isn't pinned yet, run 'rokit add rojo-rbx/rojo'. To set Rojo up by hand, see https://rogen-roblox.vercel.app/docs/v2/installation. (serve.serverFailed)Pin the tool, or fix the install that the quoted line points at. To see the full output, run rojo --version yourself.
A toolchain shim on the PATH fails this way when its project doesn't pin the tool. The message then adds the command that pins it.
serve.portTaken
Error. Another process holds the port that a config would be served on. If that process is a Rojo server, the message names the project it serves. If a rogen serve started it, the message also names the config file it was started for.
Whether this is an error depends on what started the server:
- A
rogen servefor the same project file: not an error.rogen serveleaves that server running. - A
rogen servefor another file, in this folder or another, such as a second place on the same port: an error. - Anything else, such as a
rojo serveyou ran yourself or an Argon server: an error, even when it serves a project with the same name. The message says that another process holds the port.
error: Port 34872 is taken by Rojo serving lobby, which rogen serve started for places/lobby/default.rogen.json, so places/arena/default.rogen.json can't be served there. Stop it, set a servePort in places/arena/default.rogen.json, or run 'rogen serve places/arena --port <port>'. (serve.portTaken)Stop what holds the port, give the config its own servePort in its .rogen.json, or pass a free port with --port. Serve a second place from a second terminal. In --json, fixes holds the command with a free port that Rogen found.
serve.serverExited
Error. A server stopped on its own with a non-zero exit code, or couldn't start. rogen serve then stops and exits 1.
error: Rojo stopped serving default with exit code 1; see what it said above. (serve.serverExited)Read what the server printed just above the error. It usually says why the server stopped. If the server printed nothing, as when it was killed, the message ends with without saying why.
Rojo
These diagnostics come from the Rojo that Rogen runs: a Rojo too old for what the project file uses, or a Rojo command that failed.
rojo.syncRulesUnsupported
Error. The Rojo that would run is older than 7.5.0, and a project file that Rogen wrote has syncRules. Rojo 7.5.0 is the first release that reads them, so an older Rojo would refuse the file. Rogen checks this before it serves anything.
error: Rojo 7.4.4 does not read "syncRules" before 7.5.0, and this file has 2. Change your Rojo pin to 7.5.0 or later, or update the Rojo on the PATH. (rojo.syncRulesUnsupported)Change the pin to 7.5.0 or later, run the manager's install command, and run your command again. See Installation.
A project file with no sync rules runs on an older Rojo.
rojo.negationUnsupported
Error. The Rojo that would run is older than 7.7.0, and a project file that Rogen wrote has a globIgnorePaths glob that starts with !. Rojo 7.7.0 is the first release that reads such a glob. An older Rojo reads it as a name that starts with !, which matches nothing, so the files that the glob brings back stay ignored. Rogen checks this before it serves anything.
error: Rojo 7.6.1 reads no "!" glob before 7.7.0, so it ignores what this file's 1 re-includes: "!**/Keep.spec.luau". Change your Rojo pin to 7.7.0 or later, or update the Rojo on the PATH. (rojo.negationUnsupported)Change the pin to 7.7.0 or later, run the manager's install command, and run your command again.
rojo.windowsRules
Error. On Windows, Rojo 7.7.0 applies no sync rule and no ignore glob to a file under a $path outside the project file's folder. rojo sourcemap would then list a tree that differs from the one Rogen wrote. This affects a project file that mounts a folder above its own, as a place that lists ../shared/src does, and that has any sync rule or ignore glob.
error: Rojo 7.7.0 on Windows applies no sync rule or ignore glob to a file under a "$path" outside this file's folder, and this file has 1: "../shared/src". Rojo 7.7.1 fixed it: change your Rojo pin, or update the Rojo on the PATH. (rojo.windowsRules)Move to Rojo 7.7.1 or later.
Only sourcemap stops with this error. build and serve read the file correctly on 7.7.0. Rojo 7.7.1 fixed the bug, and Rojo 7.5.0 to 7.6.1 don't have it.
rojo.commandFailed
Error. Rojo exited with an error while Rogen ran it, such as rojo build for rogen build -o. The message says how Rojo exited and what it printed.
error: 'rojo build' failed (exit code 1): failed to create file 'nodir/game.rbxl' Caused by: No such file or directory (os error 2). (rojo.commandFailed)Fix what Rojo reports, such as an output folder that doesn't exist, and run the command again.
Rogen had already written the project files when Rojo failed.
rojo.commandUnsupported
Error. The Rojo that would run doesn't have the command, because it is older than the release that added it. Today, only rogen syncback can get this error, because rojo syncback arrived in Rojo 7.7.0.
error: Rojo 7.6.1 has no 'syncback' command; Rojo 7.7.0 added it. Change your Rojo pin to 7.7.0 or later, or update the Rojo on the PATH. (rojo.commandUnsupported)Pin a newer Rojo with your toolchain manager (rokit add rojo-rbx/rojo), or update the Rojo on the PATH.
Syncback
These diagnostics come from rogen syncback, which writes the changes made in a place back to your files.
syncback.compiledPath
Warning. The project has a compiledPath, and an instance that comes from it changed in the place, was removed, or is new: a script, or a folder or model the compiler copies there. A tool such as Darklua or rbxtsc writes the compiled path from your source files, so the next compile would replace anything syncback wrote there. Syncback leaves the instance out and writes the rest, such as the folders the tree mounts.
warning: ServerScriptService/Combat/Combat changed in the place, but it is compiled into dist, so syncback left it out. Make the change in the source files. (syncback.compiledPath)
warning: ServerScriptService/Combat/Hit was removed from the place, but it is compiled into dist, so syncback left it out. Remove it from the source files. (syncback.compiledPath)
warning: ServerScriptService/Combat/Loot is new in the place, but the project compiles into dist, so syncback left it out. Add it to the source files. (syncback.compiledPath)Make the change in the source files the compiler reads.
syncback.removedFromProjectFile
Error. The place no longer holds an instance that a node of the config's own tree defines. Rojo's syncback changes the properties of a project file's nodes, but it never adds or removes a node, so it refuses. Nothing was written.
error: the place no longer holds Workspace/Map, and the tree of the config defines it, which syncback cannot remove. Remove its node from the tree, then run syncback again. (syncback.removedFromProjectFile)Remove the node from the tree of the .rogen.json, or put the instance back in the place. Then run rogen syncback again.
This error is only about the nodes that you wrote in the tree. Rogen syncs the files it placed through a mirror, so it can always remove them.
syncback.unplaced
Warning. The place holds an instance that no folder of the project can take, so syncback left it out. The message says why.
Syncback writes a new instance where routing would place a file for it, in the style of the nearest files. It can't decide where in these cases:
- No route puts files where the instance's parent is.
- Two routes do.
- The project has several source paths, and no file beside the instance says which one.
- The files beside the instance are split evenly between two folders of one style.
Syncback also uses this warning for changes that it can't write:
- an instance where an ignore glob would put it
- a property set on a folder that matches no single folder of the project
- a property set on a node that only routing made, because the
treehas no node for it - a copy of an init script that was edited differently from another copy, or deleted while another copy was edited (Rogen writes the edit)
- a change that Rojo itself can't sync back, such as a
.jsonor.tomlmodule, which Rojo skips, or a changed.yamlor.ymlmodule, which makes Rojo's syncback fail
warning: ServerScriptService/Inventory/Mail is in the place and no folder of the project can take it, so it was left out: files beside it are in more than one place, as many in each: src/Inventory/Server, lib/Inventory/Server. (syncback.unplaced)Create the file where you want it, by hand, and run rogen syncback again. The other changes from the same run were written.
syncback.misplaced
Warning. After syncback, Rogen checked where the files it wrote land, and one of them lands at a different instance than the one in the place. A route for it is missing or ambiguous, or the file's name means something to routing.
warning: this file was written for ServerScriptService/Quest/Mail, and lands at ReplicatedStorage/Shared/Quest/Mail. Move it to where routing puts it at ServerScriptService/Quest/Mail. (syncback.misplaced)Move or rename the file. Run rogen where on it to see which route places it. See Routing.
Migration
This diagnostic comes from a config written for Rogen 1.
legacy.config
Error. A .rogen.json has keys from Rogen 1, such as source, aliases or a mode. It is a v1 config, which v2 doesn't read.
error: this looks like a config for Rogen 1, which v2 doesn't read. See https://rogen-roblox.vercel.app/docs/v2/migrating-from-v1 to migrate it. (legacy.config)Rewrite the config in the v2 format. See Migrating from v1.