Requested module was required recursively

I’m making a Stellaris-style game.

  • World stores all game data like planets and the current date.
  • Helper changes that data (like advancing the date).
  • Framework connects everything and gives access to things like planet classes.
-- World.lua
local Helper = require(script.Parent.Helper)
local Manager = require(script.Parent.Manager)

local World = {
Date = DateTime.fromUniversalTime(2025, 7, 1),
Planets = { "Earth", "Mars", "Venus" },
}

function World:GetDate()
return Helper.GetCurrentDate(self)
end

function World:Tick()
print("World tick:", self:GetDate())
Manager.Update(self)
end

return World
-- Helper.lua  
local Helper = {}  

function Helper.GetCurrentDate(world)  
    return world.Date  
end  

function Helper.AdvanceDate(world, days)  
    world.Date += days  
end  

return Helper  
-- Manager.lua  
local Helper = require(script.Parent.Helper)  

local Manager = {}  

function Manager.Update(world)  
    Helper.AdvanceDate(world, 1)  
    print("Manager advanced to:", Helper.GetCurrentDate(world))  
end  

return Manager  
-- TestScript.lua  
local World = require(game.ServerScriptService.Modules.World)  
World:Tick() 

The problem:

World needs Framework → Framework includes Helper → Helper needs World.
That loop creates a cyclic dependency, meaning the modules load in a circle and break.

What are my options here, for solving this?

local toRequire = PATH.toRequire -- only get the object, not the require.

-- ... when you actually need the require

local newRequire = require(toRequire)

in this case its probably best not to have all these modules, or to just move some of the functions to different modules so this issue doesnt happen.

for instance, shouldnt the world module contain the functions that advance the date and get the current date?

I mean they do directly correlate to the world, so why not just store those functions in the world module?

as much as it sucks this is usually the best option, cause trying to abuse certain hacks usually doesnt go the best, and this way is usually easier.

tl;dr: just combine the modules

1 Like

you can make a shared module (that requires nothing) and then have each module put themselves into the shared module or whatever necessary functions

Can’t. World holds the state because the amount of data involved in this game, having both getters and setters would be a ten thousand line pile of mess. So all these modules, as a result, have to be split up to avoid this.

2 Likes

That’s what I’m doing, but the child modules still have to interface with eachother and context/dependency injection isn’t viable.

can you explain more why you cant do that

All necessary modules would have require(sharedModule), and then they can communicate with each other by giving references to themselves or their functions through the sharedModule

move the table variable of world into a separate modulescript and require it into any script/module that needs to edit or read it’s values, there’s no cycle dependency and needs minimal editing, you also wouldn’t need to pass it down the functions keeping things simpler

World module has to require Framework because Framework contains the classes referenced in World module

local Framework = require(game.ServerStorage.Framework)
local Planet = require(Framework.Classes.Planet)

local planets: Planet = {} --planet array

Splitting it into another module would retain the same behaviour anyway.

no i mean the variable and just the variable, not the modulescript, you can access variables from modulescripts just like functions by doing module. worldvar={stuffhere}

That’s what I’m doing currently yet it still requires cyclically.

Framework → holds a table of required module Helper
Helper → requires World (to view and access game state data like Planets array of planets in-game)
World → requires Framework

They constantly require eachother here, and dependency injection is a last resort because it forces the project to go from 100-200 lines of code to 300 on the lower end for all modules.

The variable is of type Planet though. Do you mean the Planets array? Because the type has to be specified as Planet class, and that requires the Framework to do so.

I’m a little confused now since I’m only going by what you’ve posted so far, but anyways for cycle dependencies you move the offending thing into another modulescript that is then required by the scripts causing the cycle, you keep doing this until it’s solved.

from what i can see since you’re accessing Date and Planets from multiple modulescripts it would be easier to just make it a global variable by putting it into it’s own modulescript that gets required by anything that needs to change or read it’s values.

you can use draw.io or paper and pencil to plan out your layout of modulescripts by making them into boxes and connecting them with lines, it makes it far easier to visualize and plan things out and fix cycle dependencies

Shared → holds a table to store modules and a getter method
Framework → requires shared, Shared.Framework = Framework
Helper → requires shared, Shared.Helper = Helper
World → requires shared, Shared.World = World

Then, replace require with just accessing from shared

Helper–> requires World requires Shared, World = Shared.Require(World)

and it should be the same amount of code since you only replace how the require works