From 434dc0ffd50f36a1077cfa4e1795fc9bd5d9792c Mon Sep 17 00:00:00 2001 From: Echo Date: Sun, 15 Feb 2026 03:28:32 -0500 Subject: [PATCH] fix(mattermost): deactivate slash state before async cleanup to prevent race Snapshot registered commands, then deactivate state immediately on abort. Prevents race where new monitor activates fresh state that gets wiped by the delayed .then() of the old monitor's cleanup promise. --- extensions/mattermost/src/mattermost/monitor.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/extensions/mattermost/src/mattermost/monitor.ts b/extensions/mattermost/src/mattermost/monitor.ts index 5ebe3c4bfa5..11d50c7094c 100644 --- a/extensions/mattermost/src/mattermost/monitor.ts +++ b/extensions/mattermost/src/mattermost/monitor.ts @@ -1134,13 +1134,16 @@ export async function monitorMattermostProvider(opts: MonitorMattermostOpts = {} // Clean up slash commands on shutdown if (slashEnabled) { const onAbortCleanup = () => { + // Snapshot registered commands before deactivating state + const commands = getSlashCommandState(account.accountId)?.registeredCommands ?? []; + // Deactivate state immediately to prevent race with re-activation + deactivateSlashCommands(account.accountId); + // Then clean up remote registrations asynchronously void cleanupSlashCommands({ client, - commands: getSlashCommandState(account.accountId)?.registeredCommands ?? [], + commands, log: (msg) => runtime.log?.(msg), - }) - .then(() => deactivateSlashCommands(account.accountId)) - .catch((err) => runtime.error?.(`mattermost: slash cleanup failed: ${String(err)}`)); + }).catch((err) => runtime.error?.(`mattermost: slash cleanup failed: ${String(err)}`)); }; opts.abortSignal?.addEventListener("abort", onAbortCleanup, { once: true }); }