OnServerEvent can only be used on the server

So I was following a tutorial and I copied exactly what he did in a module but it gave me 2 errors.


Tutorial:

This is my script for SimpleEvent.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local Events = ReplicatedStorage:WaitForChild("Events")

local Camera = workspace.CurrentCamera

local module = {}
module.Modules = {}

local CraterModule
local CameraShaker
local CameraShake

local function ShakeCamera(Preset)
	CameraShake:Shake(CameraShaker.Presets[Preset])
end

function module.Init()
	CraterModule = module.Modules.CraterModule
	CameraShaker = module.Modules.CameraShaker
	CameraShake = CameraShaker.new(Enum.RenderPriority.Camera.Value, function(ShakeCF)
		Camera.CFrame = Camera.CFrame * ShakeCF
	end)
	CameraShake:Start()
	
	Events.ShakeCamera.OnClientEvent:Connect(ShakeCamera)
	Events.CreateCrater.OnServerEvent:Connect(CraterModule.CreateCrater)
end

return module

And my script for the Crater module.

local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Events = ReplicatedStorage:WaitForChild("Events")
local CraterRocks = workspace:WaitForChild("CoreObjects"):WaitForChild("CraterRocks")

local Circle = math.pi * 2
local RNG = Random.new()

local DownDirection = Vector3.new(0, -100, 0)

local module = {}

local function getXAndZPositions(Radius, Angle)
	local x = math.cos(Angle) * Radius
	local z = math.sin(Angle) * Radius
	return x, z
end

function module.CreateCrater(OriginPosition, AmountOfRocks, Radius, Duriation, SizeMultiplier)
	if SizeMultiplier == nil then
		SizeMultiplier = 1
	end
	
	local IgnoreList = {CraterRocks}
	for _, v in Players:GetPlayers() do
		local Character = v.Character
		if Character then
			table.insert(IgnoreList, Character)
		end
	end
	
	local RayParams = RaycastParams.new()
	RayParams.FilterDescendantsInstances = IgnoreList
	RayParams.FilterType = Enum.RaycastFilterType.Exclude
	
	for i=1, AmountOfRocks do
		local Angle = (Circle / AmountOfRocks)
		local X, Z =  getXAndZPositions(Radius, Angle)
		
		local RockSizeMultiplier = RNG:NextNumber(1, 1.6)
		local RockSize = Vector3.new(RNG:NextNumber(2,4) * RockSizeMultiplier, RNG:NextNumber(2,4) * RockSizeMultiplier, RNG:NextNumber(2,4) * RockSizeMultiplier) * SizeMultiplier
		
		local OriginPositionWithoutY = Vector3.new(OriginPosition.X, 0, OriginPosition.Z)
		local XZPosition = (CFrame.new(OriginPositionWithoutY) * CFrame.new(X,0,Z)).Position
		
		local RayResult = workspace:Raycast(XZPosition + Vector3.new(0, 10, 0), DownDirection, RayParams)
		
		if RayResult then
			local Rock = Instance.new("Part")
			Rock.Size = RockSize
			Rock.Material = RayResult.Material
			Rock.Color = RayResult.Instance.Color
			Rock.Anchored = true
			Rock.CanCollide = true
			Rock.Parent = CraterRocks
			
			local FinalRockPosition = (CFrame.new(OriginPositionWithoutY) * CFrame.new(X,RayResult.Position.Y, Z)).Position
			local FinalRockCFrame = CFrame.new(FinalRockPosition, OriginPositionWithoutY) * CFrame.Angles(math.rad(RNG:NextInteger(-60, 60)), math.rad(RNG:NextNumber(-60, 60)), math.rad(RNG:NextNumber(-60, 60)))
			
			Rock.Position = FinalRockPosition + Vector3.new(0,-8,0)
			TweenService:Create(Rock, TweenInfo.new(0.1, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), {CFrame = FinalRockCFrame}):Play()
			task.delay(Duriation + i / (AmountOfRocks * 0.9), function()
				TweenService:Create(Rock, TweenInfo.new(0.3, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), {Position = FinalRockPosition + Vector3.new(0,-8,0)}):Play()
				task.wait(0.5)
				Rock:Destroy()
			end)
		end
	end
end

function module.Init()
	Events.CreateCrater.OnServerEvent:Connect(module.CreateCrater)
end

return module

so you are doing OnServerEvent on a local script? just do OnClientEvent.
Id give it a higher chance since you apparently just followed a tutorial, that you put what should be a server script, in a local script, make sure you use correct scripts.

When using a RemoteEvent to have clients and server communicate with eachother, you need to use the proper methods depending on the direction.

LocalScript (client)

local event = workspace:WaitForChild('RemoteEvent')

-- listen to event signals from server
event.OnClientEvent:Connect(function(param1, param2)
	print('client recieved event from server:', param1, param2)
end)

-- send event signals to server
event:FireServer("EatApple")

Script (server)

local event = workspace:WaitForChild('RemoteEvent')

-- listen to event signals from players
event.OnServerEvent:Connect(function(player, param1, param2)
	print('server recieved event from client:', player, param1, param2)
end)


-- wait for player
local player = nil
while not player do
	local players = game:GetService('Players'):GetPlayers()
	player = players[1]
	task.wait()
end

-- send signals to a specific player
event:FireClient(player, "You win!")

-- send signal to all players
event:FireAllClients("Actually you all win!")

Note: Clients cannot directly send eachother events, and must be routed through the server manually.

It’s actually on a module script.

but then a local script requires that module, right?

I’m using a local script to trigger the modules over here.

local LoadedModules = require(script.LoadedModules)

for _, Descendant in script:GetDescendants() do
	if Descendant.ClassName ~= "ModuleScript" or Descendant:GetAttribute("Ignore") then
		continue
	end
	
	local RequiredModule = require(Descendant)
	
	LoadedModules[Descendant.Name] = RequiredModule
end

for _, Module in LoadedModules do
	if type(Module.Modules) == "table" then
		Module.Modules = LoadedModules
	end
end

for _, Module in LoadedModules do
	if type(Module.Init) == "function" then
		task.spawn(Module.Init)
	end
end

Assuming you followed the tutorial perfectly, and nothing is wrong with code, I’m guessing this is just meant to be a server script instead of a local script.

I also have a serverscript version.
Screenshot 2025-05-01 214522

k, I dunno really what to say, thats the issue of the original topic, you can’t have onserverevent in a local script, and by requiring a module and running something that uses it, you basically just ran it on the local script, which won’t work.

Well I don’t know what script is firing the event for that error to happen. So that means I don’t know what script to fix.

Basically, :FireServer only works on client,
FireClient only works on server, onServerEvent only works on server, and vice versa. remote events are for messaging between the client and the server.

This is intended.

When you want to go Client → Server you use event.FireServer() on a Local Script, and event.onServerEvent() on a normal (Server) Script to listen for when it fires.

and when you want to go Server → Client you use event.FireClient() on a normal (Server) Script, and event.onClientEvent() in a LocalScript to listen for when it fires.

1 Like

Well I forgot to mention this, but the scripts worked in the tutorial. But not in my game. So I don’t really know what to fix. I can give you the rbxm file to show you.

you most likely just put the wrong script types and have client scripts that are meant to be server scripts. Just double check each script with what type it is meant to be in the tutorial.

1 Like