Roblox Studio error

FireServer can only be called from the client

What FireServer can only be called from the client means in Roblox Studio, the three things that cause it with the code that triggers each, and the fix for each one.

Updated 23 October 20263 min readErrorLuau

In short

A RemoteEvent has two ends. The client (a LocalScript) calls FireServer and listens with OnClientEvent. The server (a Script) calls FireClient or FireAllClients and listens with OnServerEvent. This error means one of them is in the wrong kind of script. Move that line to the other side, or swap it for its partner.

  • Server Script to one player: remote:FireClient(player, ...). To everyone: remote:FireAllClients(...).
  • LocalScript to the server: remote:FireServer(...). The server receives the player as the first argument automatically.
On this page
  1. What it means
  2. Causes and fixes
  3. Fix it with RoCode
  4. Find the line
  5. Questions
  6. Sources

What the message means

Output (example)
ServerScriptService.Shop:8: FireServer can only be called from the client

Other forms of the same message:

  • FireClient can only be called from the server
  • FireAllClients can only be called from the server
  • OnServerEvent can only be used on the server
  • OnClientEvent can only be used on the client
  • InvokeServer can only be called from the client

Which side a script runs on depends on its type and place: a Script in ServerScriptService runs on the server; a LocalScript in StarterPlayerScripts or StarterGui runs on each player's client. A Script whose RunContext is Client also runs on the client.

The same rule applies to RemoteFunctions: InvokeServer from the client, InvokeClient from the server.

Causes and fixes

Three things cause this error in practice. Each one below has the smallest code that triggers it, then the fix.

FireServer in a server Script

The server is already the server; it cannot fire to itself. This often happens when code from a LocalScript is pasted into a Script to "make it work for everyone".

Breaks Script in ServerScriptService named Round
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local showMessage = ReplicatedStorage:WaitForChild("ShowMessage")

-- in a server Script: FireServer can only be called from the client
showMessage:FireServer("Round starting!")

From the server, use FireAllClients (everyone) or FireClient(player, ...) (one player). The LocalScript listens with OnClientEvent.

Fixed Script in ServerScriptService named Round
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local showMessage = ReplicatedStorage:WaitForChild("ShowMessage") :: RemoteEvent

showMessage:FireAllClients("Round starting!")

OnServerEvent in a LocalScript

A LocalScript cannot receive what clients send to the server. Connecting to OnServerEvent there fails straight away.

Breaks LocalScript in StarterPlayerScripts named Shop
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local buyItem = ReplicatedStorage:WaitForChild("BuyItem")

-- in a LocalScript: OnServerEvent can only be used on the server
buyItem.OnServerEvent:Connect(function(player, itemName)
	print(player, itemName)
end)

Put the OnServerEvent handler in a Script in ServerScriptService. Keep only the FireServer call in the LocalScript.

Fixed Script in ServerScriptService named Shop
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local buyItem = ReplicatedStorage:WaitForChild("BuyItem") :: RemoteEvent

buyItem.OnServerEvent:Connect(function(player: Player, itemName: unknown)
	if typeof(itemName) ~= "string" then
		return
	end
	print(player.Name, "wants to buy", itemName)
end)

Always check what a client sends: its type, and whether that player is allowed to do it. The RemoteEvents guide shows the full pattern.

FireClient or FireAllClients in a LocalScript

Clients cannot message each other directly. A LocalScript that tries to tell other players something with FireAllClients fails.

Breaks LocalScript in StarterPlayerScripts named Cheer
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local cheer = ReplicatedStorage:WaitForChild("Cheer")

-- in a LocalScript: FireAllClients can only be called from the server
cheer:FireAllClients("GG!")

Send it to the server with FireServer, and let a server Script pass it on to everyone with FireAllClients.

Fixed LocalScript in StarterPlayerScripts named Cheer
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local cheer = ReplicatedStorage:WaitForChild("Cheer") :: RemoteEvent

-- client: ask the server
cheer:FireServer("GG!")

-- everyone hears it once the server passes it on
cheer.OnClientEvent:Connect(function(fromName: string, text: string)
	print(fromName .. ": " .. text)
end)

And on the server: cheer.OnServerEvent:Connect(function(player, text) cheer:FireAllClients(player.DisplayName, text) end), after checking that text is a short string. Text shown to other players must go through Roblox's text filtering.

Fix it in your place

Paste the error, RoCode fixes it in your place

Copy the line from Output and paste it here. RoCode opens the script it names in the place you have open in Studio, works out which of the causes above it is, and edits the code there instead of handing you a snippet to paste.

For example: ServerScriptService.Shop:8: FireServer can only be called from the client

RoCode is an AI agent for Roblox Studio: it reads the scripts in the place you have open, finds the line and edits it there, and every change is an undo point. It runs on Windows or macOS with a desktop browser. Free to start, with free credits every day.

How to find the line that causes it

  1. Open Output (Window menu, or the Script tab), clear it with Ctrl+K (⌘K on Mac), and press Play.
  2. Find the first red line. It starts with the script's place in the Explorer and the line number, such as ServerScriptService.Shop:12:.
  3. Click the red line. Studio opens that script with the cursor on the failing line.
  4. Read the lines between Stack Begin and Stack End under it: they list the calls that led there, newest first, so you can see which function called the broken one.
  5. Still not sure which value is wrong? Add print(typeof(x), x) just above the line, or set a breakpoint on it and read the values in the Watch window.

Questions

Which side is my script on?

A Script in ServerScriptService or Workspace runs on the server. A LocalScript in StarterPlayerScripts, StarterCharacterScripts, StarterGui or a Tool runs on the player's client. In Output, server lines are marked Server and client lines Client.

Why does the server get the player automatically?

Roblox adds the player who called FireServer as the first argument of OnServerEvent, so a client cannot pretend to be someone else.

Where should the RemoteEvent be?

In ReplicatedStorage, so both the server and every client can see it.

Can RoCode fix it?

Yes. Paste the Output line into RoCode. It moves each RemoteEvent call to the right kind of script in your open place and adds the matching handler on the other side.

Sources and further reading

How the code was checked: every block marked Fixed passes Luau's strict type checker against Roblox's API definitions (luau-lsp, 23 October 2026), and every block marked Breaks compiles and fails only when it runs. The message wording was checked against the message strings in Roblox Studio itself (macOS build of 13 October 2026) on 23 October 2026. A type check catches misspelt APIs and wrong types, not game logic, so playtest in Studio before you publish.

Stop hunting errors line by line.

RoCode reads the scripts in your open place, fixes the error where it happens and tells you what it changed. Free every day, no card required.