ChatService Added Non-Player Speaker doesn't have EventFolder

So I have a custom Chat Bot in my game and it was giving me this error:

ServerScriptService.ChatServiceRunner.Speaker:245: attempt to index field 'EventFolder' (a nil value)

Error sending internal filtered message: ServerScriptService.ChatServiceRunner.Speaker:256: attempt to index field 'EventFolder' (a nil value)

It didn’t stop the bot from functioning, but it is very annoying so I decided to try the sample chat bot given in the Developer Hub and I got the same error.

Here’s a repro place using the exact code in the article:
ChatBotTest.rbxl (31.3 KB)

The bug started happening a while ago(Not exactly sure when) and it occurs everytime someone in the game chats, including bots. It doesn’t stop the bot or anyone from chatting and seeing chat messages, however it does fill up the output which makes debugging other things very difficult.

8 Likes

Can confirm the same issue is happening at https://www.roblox.com/games/186847702/Temple-of-Memories, where we also make use of a bot (speaker created for the server) speaking in the All channel, which has been happening for over a week.

1 Like

Until this is officially fixed, I found a temporary, yet hacky, fix for this issue.

In order to do this, you will need a forked copy of the chat scripts.

Step 1:
Open the module in the following path

game.Chat.ChatServiceRunner.Speaker

Step 2:
Replace the function InternalSendMessage and InternalSendFilteredMessage, found on line 242 within the Speaker module, with the following code

function methods:InternalSendMessage(messageObj, channelName)

    local success, err = pcall(function()

        self:LazyFire("eReceivedUnfilteredMessage", messageObj, channelName)

        if self.EventFolder ~= nil then

            self.EventFolder.OnNewMessage:FireClient(self.PlayerObj, messageObj, channelName)

        end

    end)

    if not success and err then

        print("Error sending internal message: " ..err)

    end

end

function methods:InternalSendFilteredMessage(messageObj, channelName)

    local success, err = pcall(function()

        self:LazyFire("eReceivedMessage", messageObj, channelName)

        self:LazyFire("eMessageDoneFiltering", messageObj, channelName)

        if self.EventFolder ~= nil then

            self.EventFolder.OnMessageDoneFiltering:FireClient(self.PlayerObj, messageObj, channelName)

        end

    end)

    if not success and err then

        print("Error sending internal filtered message: " ..err)

    end

end

If I made a typo or mistake, feel free to reply :+1:

2 Likes

This is also happening in Adopt Me and is flooding our output

1 Like

I’m also having this issue, any word on this?

3 Likes

Having this issue as well. It only happens when I add the ModuleScript to Chat.ChatModules. The code I’m using is…

local MessageDelay = 180
local Messages = {
	"See an abusive professor or student? Use the !report command!",
	"Find a bug or have a suggestion? Use the !suggest command!",
	"Wonder how much time you have in game? Say :viewtime me",
	"After you have enough time/credits, say !rank to send a promotion request!"
}
local index = 1

local function Run(ChatService)
	local bot = ChatService:AddSpeaker("Notification")
	bot:JoinChannel("All")
	local bot_data = {
		ChatColor = Color3.new(0.8,0.3,0.4),
		NameColor = Color3.new(0.8,0.4,0.3)
	}
	
	spawn(function()
		repeat
			bot:SayMessage(Messages[index],"All",bot_data)
			index = index + 1
			if index > #Messages then
				index = 1
			end
			wait(MessageDelay)
		until false
	end)
end

return Run

And update on this would be great <3

This has started happening to me as well. It happens when I try to use the SetExtraData method.

local ChatService = require(game:GetService('ServerScriptService'):WaitForChild('ChatServiceRunner'):WaitForChild('ChatService'))

local errorCreator = ChatService:AddSpeaker('Aviron Core')
errorCreator:JoinChannel('All')
errorCreator:SetExtraData('NameColor', Color3.new(255,255,255))
errorCreator:SetExtraData('Font', Enum.Font.ArialBold)

(sorry for the messy code)

local ChatService = require(game:GetService('ServerScriptService'):WaitForChild('ChatServiceRunner'):WaitForChild('ChatService'))

local ChatSpeaker = ChatService:AddSpeaker("Bot")
ChatSpeaker:JoinChannel("All")
ChatSpeaker:SayMessage("Testing message.", "All")

This is working for me correctly. I can’t run this in the Studio, although this is working when I play live.

It works for us, but it just prints an error every time it’s used, which fills up the output very quickly.

Bumping because it still isn’t fixed. Normally, I’d just wrap it in a pcall to hide the error, but it’s already wrapped in one and prints rather than actually erroring. Really annoying.

Same issue here, happens every time I call SayMessage.

Can we please have a developer acknowledge this issue?
It’s been almost half a year.

At the very least, a developer could change how errors are thrown so that pcall can hide these false errors.
Currently, it just prints the error using print("Oopsie woopsie) and continues. I’m guessing an inexperienced programmer decided they wanted an error that doesn’t halt the script, but they didn’t know they could do spawn(function() error("Oopsie woopsie") end)

2 Likes

Still waiting for a developer to spare 5 minutes to fix this trivial issue.
I really need to be able to use speakers, but I can’t because my game prints lots of important information to the console so sabotaging my console with speakers is a no-go.

Hayo!


EDIT 2:
Easiest way to fix this issue is to remove the forked chat scripts and update to the current scripts.
If you have other additions in your Chat scripts that you would prefer to not have to re-add, then the steps below will guide you to the solution.


I took another look at the issue and fixed the Event Folder error.

I was able to quickly fix the underlying cause of that error but in doing so brings up another issue. The ChatService attempts to send data to that speaker as if it was a player object, but it is not.

I’m currently trying out a variety of quick fixes for the issue and will edit this post with any updates if there are any.

EDIT:
The fix for the issue is quick as it doesn’t take much effort to change out.
I can neither confirm nor deny that this issue is fixed in up-to-date chat scripts, but this is a fix if it is not already.


Steps 1 through 3 are optional and are not required to fix the issue.
Steps 4 and above will fix the issue


Step 1:
Open the ChatService script in your forked copy of the Chat Scripts. (game.Chat.ChatServiceRunner.ChatService)

Step 2:
Search for the method AddSpeaker (CTRL + F on windows)

Step 3:
Replace the method with this below:

function methods:AddSpeaker(speakerName)
	if (self.Speakers[speakerName:lower()]) then
		error("Speaker \"" .. speakerName .. "\" already exists!")
	end

	local speaker = Speaker.new(self, speakerName)
	self.Speakers[speakerName:lower()] = speaker
	
	speaker.EventFolder = game:GetService("ReplicatedStorage"):WaitForChild("DefaultChatSystemChatEvents")

	local success, err = pcall(function() self.eSpeakerAdded:Fire(speakerName) end)
	if not success and err then
		print("Error adding speaker: " ..err)
	end

	return speaker
end

The code above correctly adds an EventFolder to the new speaker, which was not done before.

Step 4:
Navigate to your Speaker module. Located in game.Chat.ChatServiceRunner.Speaker

Step 5:
Search for the method InternalSendMessage

Step 6: Select both the InternalSendMessage and InternalSendFilteredMessage and delete them

Step 7:
Replace the methods with the code below

function methods:InternalSendMessage(messageObj, channelName)
    local success, err = pcall(function()
        self:LazyFire("eReceivedUnfilteredMessage", messageObj, channelName)
        if self.PlayerObj then
            self.EventFolder.OnNewMessage:FireClient(self.PlayerObj, messageObj, channelName)
        end
    end)

    if not success and err then
        print("Error sending internal message: " ..err)
    end
end

function methods:InternalSendFilteredMessage(messageObj, channelName)
    local success, err = pcall(function()
        self:LazyFire("eReceivedMessage", messageObj, channelName)
        self:LazyFire("eMessageDoneFiltering", messageObj, channelName)
        if self.PlayerObj then
            self.EventFolder.OnMessageDoneFiltering:FireClient(self.PlayerObj, messageObj, channelName)
      	end
    end)

    if not success and err then
        print("Error sending internal filtered message: " ..err)
    end
end

The code above is checking whether a speaker has a player object or not, if it does not, there is no need to send it the updated message. On the other hand, if there is a player object in regard to a speaker, the filtered message will be sent to the correct player.

Thanks!

1 Like