@FreedomSlows The error comes exactly from what you suspected: Script Capabilities, a security feature introduced by Roblox.
Why this happens
Scripts in ServerScriptService have a restricted set of capabilities by default. Meanwhile, a BindableEvent located in ReplicatedStorage inherits additional capabilities (including LoadUnownedAsset and three others mentioned in the error) because ReplicatedStorage is accessible to both the client and the server.
Roblox blocks Fire() because the calling thread (your script in ServerScriptService) does not have all the required capabilities for the target (the BindableEvent in ReplicatedStorage).
That’s exactly why it works on the client side: your client scripts are in ReplicatedStorage, so they share the same capabilities as the BindableEvent. No conflict there.
Solutions
Solution 1 — Move the BindableEvent to ServerStorage (recommended)
This is the logical fix. A BindableEvent named ServerLoaded has no reason to be in ReplicatedStorage since the client doesn’t need it.
ServerStorage
└── Bindables
└── ServerLoaded
ReplicatedStorage
└── Bindables
└── ClientLoaded (this one stays here, which is correct)
Your code becomes:
local SERVER_STORAGE = game:GetService(“ServerStorage”)
– Inside Initialise()
shared.LOADED = SERVER_STORAGE.Bindables.ServerLoaded
shared.LOADED:Fire() – Works, same capability context
Solution 2 — Move the Script into ReplicatedStorage
Like your client scripts, you could place your server script in ReplicatedStorage to match capabilities. But this is not recommended: server logic does not belong in ReplicatedStorage. It’s bad architecture and a security risk.
Solution 3 — Use a BindableEvent created dynamically on the server
If you absolutely need ServerLoaded to remain in ReplicatedStorage (so the client can also listen to it), create the BindableEvent in code instead of placing it manually in the hierarchy:
– On the server, you create the event yourself
local serverLoadedEvent = Instance.new(“BindableEvent”)
serverLoadedEvent.Name = “ServerLoaded”
serverLoadedEvent.Parent = game.ReplicatedStorage.Bindables
shared.LOADED = serverLoadedEvent
shared.LOADED:Fire() – The script is the owner, no capability conflict
But be careful: if the client needs to listen to ServerLoaded, a RemoteEvent is a much better choice than a BindableEvent in ReplicatedStorage.
Final recommendation
Solution 1 is the correct one. The rule to remember:
BindableEvent = server ↔ server or client ↔ client communication → place it where the scripts that use it live
RemoteEvent = server ↔ client communication → ReplicatedStorage is correct
ServerLoaded is a purely server-side signal, so ServerStorage is its natural home.