Yeld getting a ModuleScript from LocalScript

I’m having a problem with a script I’ve developed for my game in Roblox. In a LocalScript, I’m trying to access a ModuleScript named RetailDataManager located in ServerScriptService. However, I keep receiving a warning saying “Infinite yield possible on 'ServerScriptService(“RetailDataManager”)” when I try to access it.

I’ve tried everything, and I still only get the error in Localscript with Yeld that I can’t find that RetailDataManager

Those are the codes:

LocalScript:

local Players = game:GetService("Players")
local player = Players.LocalPlayer
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local ServerScriptService = game:GetService("ServerScriptService")
local RetailDataManager = require(ServerScriptService:WaitForChild('RetailDataManager'))

local SetSlotNameEvent = ReplicatedStorage:WaitForChild("SetSlotName")

local SlotMenu = script.Parent:WaitForChild('SlotMenu')
local MainMenu = SlotMenu.MainMenu
local ScrollingFrameSlot = MainMenu.ScrollingFrame
local SlotTemplate = ScrollingFrameSlot:WaitForChild("SlotTemplate")
local SlotTemplateInfoFrame = SlotTemplate.InfoFrame
local InfoFrameCashLabel = SlotTemplateInfoFrame.CashInfo
local ActionButton = SlotTemplate.Button
local ShopNameLabel = SlotTemplate.ShopName

local SetShopNameFrame = SlotMenu.SetShopNameFrame
local TextBoxFrame = SetShopNameFrame.TextBoxFrame
local TextBox = TextBoxFrame.TextBox

local function InitializeSlots()
     for i = 1, 2 do
          local slot = SlotTemplate:Clone()
          slot.Visible = true
          slot.Name = "Slot" .. i
          slot.Parent = ScrollingFrameSlot

          local actionButton = slot:WaitForChild("Button")
          local shopNameLabel = slot:WaitForChild("ShopName")

          if RetailDataManager.RetailData[player.UserId] then
               local retailData = RetailDataManager.RetailData[player.UserId][i]
               if retailData then
                    shopNameLabel.Text = retailData.Name
               else
                    shopNameLabel.Text = "Create a Retail"
               end
          else
               shopNameLabel.Text = "Create a Retail"
          end

          actionButton.MouseButton1Click:Connect(function()
               SlotMenu.SetShopNameFrame.Visible = true 
               local textBox = SlotMenu.SetShopNameFrame.TextBoxFrame.TextBox

               textBox.FocusLost:Connect(function(enterPressed)
                    if enterPressed then
                         local shopName = textBox.Text
                         if #shopName >= 3 and #shopName <= 25 then
                              SetSlotNameEvent:FireServer(i, shopName)
                              textBox.Text = ""
                              SlotMenu.SetShopNameFrame.Visible = false
                         else
                              warn("Name must be between 3 and 25 characters.")
                         end
                    end
               end)
          end)
     end
end

InitializeSlots()

Script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RetailDataManager = require(script.Parent.Parent.RetailDataManager)
local SetSlotNameEvent = ReplicatedStorage:WaitForChild('SetSlotName')

print("RetailDataManager loaded successfully")

SetSlotNameEvent.OnServerEvent:Connect(function(player, slotIndex, shopName)
     print("Received SetSlotNameEvent from client")
     local success = RetailDataManager:SetSlotName(player, slotIndex, shopName)
     if success then
          print("Shop name set successfully for Slot " .. slotIndex)
     else
          warn("Failed to set shop name for Slot " .. slotIndex)
     end
end)

game.Players.PlayerAdded:Connect(function(player)
     RetailDataManager:LoadRetailData(player)
end)

ModuleScript(RetailDataManager)

local DataStoreService = game:GetService("DataStoreService") 
local RetailDataStore = DataStoreService:GetDataStore("RetailDataStore")
local Module = {}

Module.RetailData = {}

function Module:LogError(errorType)
     local errorMessages = {
          ["SaveError"] = "Error: Could not save the retail data.",
          ["LoadError"] = "Error: Could not load the retail data.",
          ["NameError"] = "Error: Invalid name length for retail (must be 3-25 characters).",
          ["GamepassError"] = "Error: Gamepass verification failed.",
          ["SlotUnavailable"] = "Error: The selected slot is unavailable.",
          ["NameExists"] = "Error: A retail with this name already exists.",
          ["UnauthorizedAccess"] = "Error: Unauthorized access attempt.",
          ["DataStoreLimit"] = "Error: DataStore limit reached. Try again later.",
          ["UnknownError"] = "An unknown error has occurred."
     }
     local message = errorMessages[errorType] or errorMessages["UnknownError"]
     warn(message)
end


function Module:LogSuccess(successType)
     local successMessages = {
          ["CreatingRetail"] = "Creating Retail...",
          ["SettingUpName"] = "Setting Up Retail's Name...",
          ["SavingData"] = "Saving Retail Data...",
          ["LoadingData"] = "Loading Retail Data...",
          ["SlotUnlocked"] = "Slot unlocked successfully!",
          ["PurchaseComplete"] = "Gamepass purchased successfully!",
          ["RetailLoaded"] = "Retail loaded successfully!",
          ["DataSaved"] = "Retail data saved successfully.",
          ["DataLoaded"] = "Retail data loaded successfully."
     }
     local message = successMessages[successType] or "Process completed successfully."
     print(message)
end

function Module:SetSlotName(player, slotIndex, shopName)
     if #shopName < 3 or #shopName > 25 then
          self:LogError("NameError")
          return false
     end

  
     Module.RetailData[player.UserId] = Module.RetailData[player.UserId] or {}

     if Module.RetailData[player.UserId][slotIndex] and Module.RetailData[player.UserId][slotIndex].Configured then
          self:LogError("SlotUnavailable")
          return false
     end

     Module.RetailData[player.UserId][slotIndex] = {
          Name = shopName,
          Configured = true
     }

     self:LogSuccess("SettingUpName")
     return true
end


function Module:LoadRetailData(player)
     local success, data = pcall(function()
          return RetailDataStore:GetAsync(tostring(player.UserId))
     end)

     if success then
          if data then
               Module.RetailData[player.UserId] = data
               self:LogSuccess("DataLoaded")
          else
               Module.RetailData[player.UserId] = {
                    [1] = { Name = "Create a Retail", Configured = false },
                    [2] = { Name = "Create a Retail", Configured = false }
               }
               self:LogSuccess("DataInitialized")
          end
     else
          self:LogError("LoadError")
     end
end

return Module


Can you tell me what the solution would be, and what alternative to use?

You can’t access Server services (e.g. ServerScriptService) from the client. That is the entire point of their existence.

And how can i get the functions from ModuleScript from a localscript?

You don’t need to change how you’re accessing the module, you need to change its parent from a service which is only accessible by the server to a different parent which can be accessed from the client.

ServerScriptService, which is the parent your module is under, is special because it doesn’t show the client what it contains. Same goes for ServerStorage. Both of these are meant to store objects for your game that should usually only be accessible by the server.

You could move the module to ReplicatedStorage, which is a service that replicates its contents to both the server and the client.

1 Like

I modified to connect to the DataStore from Module Script with some events, it works well. Thanks for the help buddy!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.