From 8dd416151401876ca555be38cb8b8ef2e9d799dc Mon Sep 17 00:00:00 2001 From: Jeon Suyeol Date: Thu, 5 Mar 2026 22:23:24 +0900 Subject: [PATCH 1/3] Improve Slack error messages with consistent wording and actionable hints Standardize workspace-missing messages to 'No current workspace set' across auth status and reaction commands. Add recovery hints to workspace-not-found and file-not-found errors. Include timestamp in reaction message-not-found error for debugging. --- src/platforms/slack/commands/auth.ts | 12 ++++++++++-- src/platforms/slack/commands/file.ts | 7 ++++++- src/platforms/slack/commands/reaction.ts | 8 ++++---- src/platforms/slack/commands/workspace.ts | 14 ++++++++++++-- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/platforms/slack/commands/auth.ts b/src/platforms/slack/commands/auth.ts index 2c83631..b37c83d 100644 --- a/src/platforms/slack/commands/auth.ts +++ b/src/platforms/slack/commands/auth.ts @@ -133,7 +133,15 @@ async function logoutAction(workspace: string | undefined, options: { pretty?: b } if (!config.workspaces[targetWorkspace]) { - console.log(formatOutput({ error: `Workspace not found: ${targetWorkspace}` }, options.pretty)) + console.log( + formatOutput( + { + error: `Workspace not found: ${targetWorkspace}`, + hint: 'Run "workspace list" to see available workspaces.', + }, + options.pretty, + ), + ) process.exit(1) } @@ -151,7 +159,7 @@ async function statusAction(options: { pretty?: boolean }): Promise { const ws = await credManager.getWorkspace() if (!ws) { - console.log(formatOutput({ error: 'No workspace configured. Run "auth extract" first.' }, options.pretty)) + console.log(formatOutput({ error: 'No current workspace set. Run "auth extract" first.' }, options.pretty)) process.exit(1) } diff --git a/src/platforms/slack/commands/file.ts b/src/platforms/slack/commands/file.ts index 174cf47..f8de5dd 100644 --- a/src/platforms/slack/commands/file.ts +++ b/src/platforms/slack/commands/file.ts @@ -94,7 +94,12 @@ async function infoAction(fileId: string, options: { pretty?: boolean }): Promis const fileData = files.find((f) => f.id === fileId) if (!fileData) { - console.log(formatOutput({ error: `File not found: ${fileId}` }, options.pretty)) + console.log( + formatOutput( + { error: `File not found: ${fileId}`, hint: 'Run "file list" to see available files.' }, + options.pretty, + ), + ) process.exit(1) } diff --git a/src/platforms/slack/commands/reaction.ts b/src/platforms/slack/commands/reaction.ts index e7dc8f8..970a1d4 100644 --- a/src/platforms/slack/commands/reaction.ts +++ b/src/platforms/slack/commands/reaction.ts @@ -10,7 +10,7 @@ async function addAction(channel: string, ts: string, emoji: string, options: { const ws = await credManager.getWorkspace() if (!ws) { - console.log(formatOutput({ error: 'No workspace configured. Run "auth extract" first.' }, options.pretty)) + console.log(formatOutput({ error: 'No current workspace set. Run "auth extract" first.' }, options.pretty)) process.exit(1) } @@ -40,7 +40,7 @@ async function removeAction(channel: string, ts: string, emoji: string, options: const ws = await credManager.getWorkspace() if (!ws) { - console.log(formatOutput({ error: 'No workspace configured. Run "auth extract" first.' }, options.pretty)) + console.log(formatOutput({ error: 'No current workspace set. Run "auth extract" first.' }, options.pretty)) process.exit(1) } @@ -70,7 +70,7 @@ async function listAction(channel: string, ts: string, options: { pretty?: boole const ws = await credManager.getWorkspace() if (!ws) { - console.log(formatOutput({ error: 'No workspace configured. Run "auth extract" first.' }, options.pretty)) + console.log(formatOutput({ error: 'No current workspace set. Run "auth extract" first.' }, options.pretty)) process.exit(1) } @@ -82,7 +82,7 @@ async function listAction(channel: string, ts: string, options: { pretty?: boole console.log( formatOutput( { - error: 'Message not found', + error: `Message not found: ${ts}`, channel, ts, }, diff --git a/src/platforms/slack/commands/workspace.ts b/src/platforms/slack/commands/workspace.ts index e32e90e..c427d9d 100644 --- a/src/platforms/slack/commands/workspace.ts +++ b/src/platforms/slack/commands/workspace.ts @@ -27,7 +27,12 @@ async function switchAction(id: string, options: { pretty?: boolean }): Promise< const config = await credManager.load() if (!config.workspaces[id]) { - console.log(formatOutput({ error: `Workspace not found: ${id}` }, options.pretty)) + console.log( + formatOutput( + { error: `Workspace not found: ${id}`, hint: 'Run "workspace list" to see available workspaces.' }, + options.pretty, + ), + ) process.exit(1) } @@ -65,7 +70,12 @@ async function removeAction(id: string, options: { pretty?: boolean }): Promise< const config = await credManager.load() if (!config.workspaces[id]) { - console.log(formatOutput({ error: `Workspace not found: ${id}` }, options.pretty)) + console.log( + formatOutput( + { error: `Workspace not found: ${id}`, hint: 'Run "workspace list" to see available workspaces.' }, + options.pretty, + ), + ) process.exit(1) } From b7e5544ba02525dbb4444efc4e558bf6d54c6e80 Mon Sep 17 00:00:00 2001 From: Jeon Suyeol Date: Thu, 5 Mar 2026 22:25:07 +0900 Subject: [PATCH 2/3] Improve Discord and Discordbot error messages with actionable hints --- src/platforms/discord/commands/server.ts | 17 +++++++++++++++-- src/platforms/discordbot/client.ts | 5 ++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/platforms/discord/commands/server.ts b/src/platforms/discord/commands/server.ts index 5ec930d..27a1e1b 100644 --- a/src/platforms/discord/commands/server.ts +++ b/src/platforms/discord/commands/server.ts @@ -54,7 +54,12 @@ export async function switchAction(serverId: string, options: { pretty?: boolean const config = await credManager.load() if (!config.servers[serverId]) { - console.log(formatOutput({ error: `Server not found: ${serverId}` }, options.pretty)) + console.log( + formatOutput( + { error: `Server not found: ${serverId}`, hint: 'Run "server list" to see available servers.' }, + options.pretty, + ), + ) process.exit(1) } @@ -78,7 +83,15 @@ export async function currentAction(options: { pretty?: boolean }): Promise".', + }, + options.pretty, + ), + ) process.exit(1) } diff --git a/src/platforms/discordbot/client.ts b/src/platforms/discordbot/client.ts index caaf535..87af5f3 100644 --- a/src/platforms/discordbot/client.ts +++ b/src/platforms/discordbot/client.ts @@ -334,7 +334,10 @@ export class DiscordBotClient { const channels = await this.listChannels(guildId) const found = channels.find((c) => c.name === channel || c.name === channel.replace(/^#/, '')) if (!found) { - throw new DiscordBotError(`Channel not found: "${channel}"`, 'channel_not_found') + throw new DiscordBotError( + `Channel not found: "${channel}". Use channel ID or exact channel name.`, + 'channel_not_found', + ) } return found.id } From 475094e39626007493c457765eeb7f568f33d19c Mon Sep 17 00:00:00 2001 From: Jeon Suyeol Date: Thu, 5 Mar 2026 22:25:15 +0900 Subject: [PATCH 3/3] Improve Teams error messages with actionable recovery guidance --- src/platforms/teams/client.ts | 4 ++-- src/platforms/teams/commands/team.ts | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/platforms/teams/client.ts b/src/platforms/teams/client.ts index 65ed783..4b0b181 100644 --- a/src/platforms/teams/client.ts +++ b/src/platforms/teams/client.ts @@ -86,7 +86,7 @@ export class TeamsClient { private async request(method: string, path: string, body?: unknown, baseUrl: string = MSG_API_BASE): Promise { if (this.isTokenExpired()) { - throw new TeamsError('Token has expired', 'token_expired') + throw new TeamsError('Token has expired. Run "auth extract" to refresh.', 'token_expired') } const url = `${baseUrl}${path}` @@ -151,7 +151,7 @@ export class TeamsClient { private async requestFormData(path: string, formData: FormData, baseUrl: string = MSG_API_BASE): Promise { if (this.isTokenExpired()) { - throw new TeamsError('Token has expired', 'token_expired') + throw new TeamsError('Token has expired. Run "auth extract" to refresh.', 'token_expired') } const url = `${baseUrl}${path}` diff --git a/src/platforms/teams/commands/team.ts b/src/platforms/teams/commands/team.ts index c31599a..8d9a5fb 100644 --- a/src/platforms/teams/commands/team.ts +++ b/src/platforms/teams/commands/team.ts @@ -53,7 +53,12 @@ export async function switchAction(teamId: string, options: { pretty?: boolean } const account = await credManager.getCurrentAccount() if (!account?.teams?.[teamId]) { - console.log(formatOutput({ error: `Team not found: ${teamId}` }, options.pretty)) + console.log( + formatOutput( + { error: `Team not found: ${teamId}`, hint: 'Run "team list" to see available teams.' }, + options.pretty, + ), + ) process.exit(1) } @@ -87,18 +92,23 @@ export async function removeAction(teamId: string, options: { pretty?: boolean } const config = await credManager.loadConfig() if (!config) { - console.log(formatOutput({ error: 'No configuration found.' }, options.pretty)) + console.log(formatOutput({ error: 'No configuration found. Run "auth extract" first.' }, options.pretty)) process.exit(1) } const account = await credManager.getCurrentAccount() if (!account) { - console.log(formatOutput({ error: 'No active account.' }, options.pretty)) + console.log(formatOutput({ error: 'No active account. Run "auth extract" first.' }, options.pretty)) process.exit(1) } if (!account.teams[teamId]) { - console.log(formatOutput({ error: `Team not found: ${teamId}` }, options.pretty)) + console.log( + formatOutput( + { error: `Team not found: ${teamId}`, hint: 'Run "team list" to see available teams.' }, + options.pretty, + ), + ) process.exit(1) }