(Knit Service) attempt to index userdata with 'Fire'

I’m quite new to Knit but I’m trying to learn it.

I’ve been learning from the documentation on GitHub and I’m on Server To Client Communication

This is almost exactly copy and pasted and its still doesnt work. When trying to Fire “ClientEvent” It says its UserData and is not a Signal/Event

Someone please help ive spent a sad amount of time trying to fix this simple problem

local Knit = require(game:GetService("ReplicatedStorage").Packages.Knit)

local Service = Knit.CreateService({ Name = "Service", Client = {} })

Service.Client.ClientEvent = Knit.CreateSignal()

function AbilityHandler(Player)

	Service.Client.ClientEvent:Fire(Player)

end)

return AbilityHandler

attempt to index userdata with 'Fire’

1 Like

Can’t help you much without seeing your KnitServer script, but I’m guessing you’re not adding the service before AbilityHandler gets called. Here’s an example Service script that’s correctly set up:

local Knit = require(game:GetService("ReplicatedStorage").Packages.Knit)

local AbilityService = Knit.CreateService {
	Name = "AbilityService ";
	Client = {
		ClientEvent  = Knit.CreateSignal(); -- Create the signal
	};
}

function AbilityService :AbilityHandler(player)
	print("Adding...")
	self.Client.ClientEvent:Fire(player)
	print("... success!")
end

return AbilityService 

Here’s an example KnitServer script that will throw the error you mentioned even though the Service itself is set up correctly:

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

local Knit = require(ReplicatedStorage.Packages.Knit)

Knit.AddServices(ServerStorage.Services)

game.Players.PlayerAdded:Connect(function(player)
	require(ServerStorage.Services.AbilityService ):AbilityHandler(player, 10)
end)

--Ensure Knit starts *after* PlayerAdded callback calls AbilityHandler
game.Players.PlayerAdded:Wait()
wait()

Knit.Start():andThen(function()
	print("Knit started server")
end)

Aaaand here’s how to fix that:

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

local Knit = require(ReplicatedStorage.Packages.Knit)

Knit.AddServices(ServerStorage.Services)

Knit.Start():andThen(function()
	print("Knit started server")
end)

game.Players.PlayerAdded:Connect(function(player)
	require(ServerStorage.Services.AbilityService):AbilityHandler(player, 10)
end)

The broken one is just like a normal KnitServer script, except it calls AbilityHandler before Knit is Started. This makes sense if you look at the source code for KnitServer:

--..inside KnitServer.Start
-- Bind remotes:
for _,service in pairs(services) do
    local middleware = service.Middleware or {}
    local inbound = middleware.Inbound or knitMiddleware.Inbound
    local outbound = middleware.Outbound or knitMiddleware.Outbound
    service.Middleware = nil
    for k,v in pairs(service.Client) do
        if type(v) == "function" then
            service.KnitComm:WrapMethod(service.Client, k, inbound, outbound)
        elseif v == SIGNAL_MARKER then
            service.Client[k] = service.KnitComm:CreateSignal(k, inbound, outbound)
        elseif type(v) == "table" and v[1] == PROPERTY_MARKER then
            service.Client[k] = service.KnitComm:CreateProperty(k, v[2], inbound, outbound)
        end
    end
end

You can see that it calls KnitComm:CreateSignal on the signal you passed and assigns the return value to the key that the signal was previously at, so Service.Client.ClientEvent is a completely different thing after KnitStart. Knit.CreateSignal doesn’t actually return a signal that you can call Fire on, it has to be processed by Knit.Start first.

In short, start Knit *before using any Service". This is also how the examples work, although I haven’t spotted anywhere that they explicitly call it out.

1 Like

Okay I do feel like it is because of the execution order but the above hasn’t fixed it.

This is the code in full

ServerScript

ReplicatedStorage = game:GetService("ReplicatedStorage")
Knit = require(ReplicatedStorage.Packages.Knit)

AnotherService = Knit.CreateService({Name = "AnotherService", Client = {}})

Knit.AddServices(script.Parent.Services) -- Moved the abilityService into a folder called Services

Signal = require(Knit.Util.Signal)
AnotherService.ServiceEvent = Signal.new()


Knit.Start():andThen(function()
	print("Knit started server")
end)

game.Players.PlayerAdded:Connect(function(Player)

	AnotherService.ServiceEvent:Fire(Player)

end)

Module


ReplicatedStorage = game:GetService("ReplicatedStorage")
Knit = require(ReplicatedStorage.Packages.Knit)

AnotherService = Knit.GetService("AnotherService")

local Service = Knit.CreateService { Name = "Service ", Client = {} }

Service.Client.ClientEvent = Knit.CreateSignal()

AbilityHandler = AnotherService.ServiceEvent:Connect(function(Player)
	Service.Client.ClientEvent:Fire(Player)
end)

return AbilityHandler

It might be because im creating a service in a module script which is being called from the serverscript which is ment to be initialising it?

Also apologise for the organisation im not really sure how this service is ment to be set up

You’re getting another error now. Or at least I am, when I try with your code:

It’s pretty self-explanatory if you read the docs, check out Services | Knit, KnitInit and KnitStart

Ye sorry forgot to close this thread. It was because of the execution order, I was tring to use the service before Knit had started. And then I tried to use GetService() Before knit had started.

Thanks for all the help

1 Like