Error occurred while calling TextChatService.OnIncomingMessage: Script that implemented this callback has been destroyed while calling async callback

Greetings I have scripted a donation effect using MessagingService so that effect would be visible on all servers. However the script also creates a system message. Since I use the updated version of Roblox’s chat system I am unable to use SetCore. Therefore I am using this as a local script under PlayerGui:

game:GetService("ReplicatedStorage"):WaitForChild("SystemMessage").OnClientEvent:Connect(function(UserId, Value, Country)
	game:GetService("TextChatService").OnIncomingMessage = function(textChatMessage)
		if textChatMessage.Metadata == "Donated" then
			local overrideProperties = Instance.new("TextChatMessageProperties")
			overrideProperties.Text = string.format("<font color='#c32cb4'>%s</font>", textChatMessage.Text)
			return overrideProperties
		else
			return nil
		end
	end
	
	game.TextChatService.TextChannels.RBXSystem:DisplaySystemMessage(game.Players:GetNameFromUserIdAsync(UserId).." has donated "..Value.."to "..Country, "Donated")
end)

It does its job properly. However after some period of time I keep on receiving this error message when attempting to send a message (this means no one can send any messages anymore):

image

I have checked which script sends this error and it seems it obviously is a script created by Roblox itself. That script seems to be a module and is named “mapDispatchToPros”. The code is below:

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

local ExperienceChat = script:FindFirstAncestor("ExperienceChat")
local Packages = ExperienceChat.Parent
local Promise = require(Packages.Promise)
local List = require(Packages.llama).List

local Analytics = require(ExperienceChat.Analytics)
local Logger = require(script.Parent.Logger)
local Config = require(ExperienceChat.Config)
local autoCastCommand = require(ExperienceChat.Commands.autoCastCommand)
local RBXWhisperCommand = require(ExperienceChat.Commands.Whisper.RBXWhisperCommand)

local ChatInputBarResetTargetChannel = require(ExperienceChat.Actions.ChatInputBarResetTargetChannel)
local UserInteraction = require(ExperienceChat.Actions.UserInteraction)

return function(dispatch)
	return {
		activateWhisperMode = function(toWhisperUserId: number)
			local toWhisperUser = Players:GetPlayerByUserId(toWhisperUserId)
			local localPlayer = Players.LocalPlayer
			if not toWhisperUser then
				return
			end
			if toWhisperUser == localPlayer then
				return
			end

			assert(localPlayer, "Players.LocalPlayer should be non-nil")

			local toWhisperUsername = toWhisperUser.Name
			local promises = {
				autoCastCommand(RBXWhisperCommand, localPlayer.UserId, "/w @" .. toWhisperUsername),
			}
			Promise.any(promises):catch(function(error)
				Logger:debug("Could not send autoCastCommand. Error: {}", error)
			end)
		end,

		resetTargetChannel = function()
			dispatch(ChatInputBarResetTargetChannel())
		end,

		onHovered = function()
			dispatch(UserInteraction("hover"))
		end,

		onUnhovered = function()
			dispatch(UserInteraction("unhover"))
		end,

		onSendChat = function(message: string)
			local chatInputBarConfiguration = TextChatService:FindFirstChildOfClass("ChatInputBarConfiguration")
			local targetTextChannel = nil
			if chatInputBarConfiguration then
				targetTextChannel = chatInputBarConfiguration.TargetTextChannel
			end

			Logger:debug("onSendChat: {} to {}", message, if targetTextChannel then targetTextChannel.Name else "nil")
			if targetTextChannel then
				Promise.try(function()
					targetTextChannel:SendAsync(message)

					local numParticipants = List.count(targetTextChannel:GetChildren(), function(instance)
						return instance:IsA("TextSource")
					end)

					local args = {
						channelName = targetTextChannel.Name,
						senderUserId = if Players.LocalPlayer then Players.LocalPlayer.UserId else nil,
						numParticipants = numParticipants,
						isDefaultChannel = if Config[targetTextChannel.Name] then "true" else "false",
					}

					Analytics.FireClientAnalyticsWithEventName("LuaMessageSent", args)
				end):catch(function(e)
					warn(e.error)
				end)
			else
				Logger:warning("TargetTextChannel was nil!")
			end
		end,
	}
end

I have attempted to find the issue but came to a dead end. Any help is highly appreciated!

P.S: I have been told that the issue is because of calling TextChatService within TextChatService.OnIncomingMessage() I have tried to remove that code but it seems the issue is still there.

There are a couple of issues here, but the main one is that you’re calling TextChatService.OnIncomingMessage from within TextChatService.OnIncomingMessage.
This is a huge no-no because the latter is called by the former. It’s like you’re trying to call yourself on the phone.
You should really not be doing this.

Instead, you should be using TextChatService.OnMessageAdded. It gets called after the message is added to a text channel, so it’s safe to modify the message at this point.

Finally, you’re doing a lot of string.formats that you don’t need. You can do this:
overrideProperties.Text = string.format("<font color=’#c32cb4’>%s</font>", textChatMessage.Text)

Like this:
overrideProperties.Text = “<font color=’#c32cb4’>” … textChatMessage.Text … “</font>”