diff --git a/extensions/bluebubbles/src/attachments.ts b/extensions/bluebubbles/src/attachments.ts index 69193322460..e9466da98e7 100644 --- a/extensions/bluebubbles/src/attachments.ts +++ b/extensions/bluebubbles/src/attachments.ts @@ -1,5 +1,6 @@ import crypto from "node:crypto"; import path from "node:path"; +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { resolveBlueBubblesServerAccount } from "./account-resolve.js"; import { assertMultipartActionOk, postMultipartFormData } from "./multipart.js"; import { @@ -130,7 +131,7 @@ export async function downloadBlueBubblesAttachment( cause: error, }); } - const text = error instanceof Error ? error.message : String(error); + const text = formatErrorMessage(error); throw new Error(`BlueBubbles attachment download failed: ${text}`, { cause: error }); } } diff --git a/extensions/bluebubbles/src/monitor.ts b/extensions/bluebubbles/src/monitor.ts index 8bf1161d040..92ec9e980c7 100644 --- a/extensions/bluebubbles/src/monitor.ts +++ b/extensions/bluebubbles/src/monitor.ts @@ -1,5 +1,6 @@ import type { IncomingMessage, ServerResponse } from "node:http"; import { safeEqualSecret } from "openclaw/plugin-sdk/browser-security-runtime"; +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { isPrivateNetworkOptInEnabled } from "openclaw/plugin-sdk/ssrf-runtime"; import { createBlueBubblesDebounceRegistry } from "./monitor-debounce.js"; import { @@ -92,7 +93,7 @@ function parseBlueBubblesWebhookPayload( try { return { ok: true, value: JSON.parse(payload) as unknown }; } catch (error) { - return { ok: false, error: error instanceof Error ? error.message : String(error) }; + return { ok: false, error: formatErrorMessage(error) }; } } } diff --git a/extensions/bluebubbles/src/probe.ts b/extensions/bluebubbles/src/probe.ts index 7e6cc350c3e..27b0a36bdc5 100644 --- a/extensions/bluebubbles/src/probe.ts +++ b/extensions/bluebubbles/src/probe.ts @@ -1,3 +1,4 @@ +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import type { BaseProbeResult } from "./runtime-api.js"; import { normalizeSecretInputString } from "./secret-input.js"; import { buildBlueBubblesApiUrl, blueBubblesFetchWithTimeout } from "./types.js"; @@ -172,7 +173,7 @@ export async function probeBlueBubbles(params: { return { ok: false, status: null, - error: err instanceof Error ? err.message : String(err), + error: formatErrorMessage(err), }; } } diff --git a/extensions/discord/src/audit.ts b/extensions/discord/src/audit.ts index f1cec274ff1..32b6790179e 100644 --- a/extensions/discord/src/audit.ts +++ b/extensions/discord/src/audit.ts @@ -3,6 +3,7 @@ import type { DiscordGuildChannelConfig, DiscordGuildEntry, } from "openclaw/plugin-sdk/config-runtime"; +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { isRecord } from "openclaw/plugin-sdk/text-runtime"; import { inspectDiscordAccount } from "./account-inspect.js"; import { fetchChannelPermissionsDiscord } from "./send.js"; @@ -124,7 +125,7 @@ export async function auditDiscordChannelPermissions(params: { channels.push({ channelId, ok: false, - error: err instanceof Error ? err.message : String(err), + error: formatErrorMessage(err), matchKey: channelId, matchSource: "id", }); diff --git a/extensions/discord/src/channel.ts b/extensions/discord/src/channel.ts index 59776e22bb7..c6e1232e8bd 100644 --- a/extensions/discord/src/channel.ts +++ b/extensions/discord/src/channel.ts @@ -16,6 +16,7 @@ import { createChannelDirectoryAdapter, createRuntimeDirectoryLiveAdapter, } from "openclaw/plugin-sdk/directory-runtime"; +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime"; import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-runtime"; import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env"; @@ -676,7 +677,7 @@ export const discordPlugin: ChannelPlugin ], }; } catch (err) { - const message = err instanceof Error ? err.message : String(err); + const message = formatErrorMessage(err); details.permissions = { channelId: parsedTarget.id, error: message }; return { details, diff --git a/extensions/discord/src/draft-stream.ts b/extensions/discord/src/draft-stream.ts index ab49b13fbc3..417e6857bf6 100644 --- a/extensions/discord/src/draft-stream.ts +++ b/extensions/discord/src/draft-stream.ts @@ -1,6 +1,7 @@ import type { RequestClient } from "@buape/carbon"; import { Routes } from "discord-api-types/v10"; import { createFinalizableDraftLifecycle } from "openclaw/plugin-sdk/channel-lifecycle"; +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; /** Discord messages cap at 2000 characters. */ const DISCORD_STREAM_MAX_CHARS = 2000; @@ -98,9 +99,7 @@ export function createDiscordDraftStream(params: { return true; } catch (err) { streamState.stopped = true; - params.warn?.( - `discord stream preview failed: ${err instanceof Error ? err.message : String(err)}`, - ); + params.warn?.(`discord stream preview failed: ${formatErrorMessage(err)}`); return false; } }; diff --git a/extensions/discord/src/monitor/gateway-plugin.ts b/extensions/discord/src/monitor/gateway-plugin.ts index fda66c215c8..aee3aeaea61 100644 --- a/extensions/discord/src/monitor/gateway-plugin.ts +++ b/extensions/discord/src/monitor/gateway-plugin.ts @@ -2,6 +2,7 @@ import * as carbonGateway from "@buape/carbon/gateway"; import type { APIGatewayBotInfo } from "discord-api-types/v10"; import * as httpsProxyAgent from "https-proxy-agent"; import type { DiscordAccountConfig } from "openclaw/plugin-sdk/config-runtime"; +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { danger } from "openclaw/plugin-sdk/runtime-env"; import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env"; import * as undici from "undici"; @@ -117,7 +118,7 @@ async function fetchDiscordGatewayInfo(params: { }); } catch (error) { throw createGatewayMetadataError({ - detail: error instanceof Error ? error.message : String(error), + detail: formatErrorMessage(error), transient: true, cause: error, }); @@ -128,7 +129,7 @@ async function fetchDiscordGatewayInfo(params: { body = await response.text(); } catch (error) { throw createGatewayMetadataError({ - detail: error instanceof Error ? error.message : String(error), + detail: formatErrorMessage(error), transient: true, cause: error, }); diff --git a/extensions/discord/src/probe.ts b/extensions/discord/src/probe.ts index b7285128168..63749db7c8c 100644 --- a/extensions/discord/src/probe.ts +++ b/extensions/discord/src/probe.ts @@ -1,4 +1,5 @@ import type { BaseProbeResult } from "openclaw/plugin-sdk/channel-contract"; +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { resolveFetch } from "openclaw/plugin-sdk/fetch-runtime"; import { fetchWithTimeout } from "openclaw/plugin-sdk/text-runtime"; import { normalizeDiscordToken } from "./token.js"; @@ -167,7 +168,7 @@ export async function probeDiscord( return { ...result, status: err instanceof Response ? err.status : result.status, - error: err instanceof Error ? err.message : String(err), + error: formatErrorMessage(err), elapsedMs: Date.now() - started, }; } diff --git a/extensions/discord/src/voice-message.ts b/extensions/discord/src/voice-message.ts index ec0eae5b7cd..00cba9e5ee9 100644 --- a/extensions/discord/src/voice-message.ts +++ b/extensions/discord/src/voice-message.ts @@ -14,6 +14,7 @@ import crypto from "node:crypto"; import fs from "node:fs/promises"; import path from "node:path"; import { RateLimitError, type RequestClient } from "@buape/carbon"; +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { parseFfprobeCodecAndSampleRate, runFfmpeg, @@ -72,7 +73,7 @@ export async function getAudioDuration(filePath: string): Promise { } return Math.round(duration * 100) / 100; // Round to 2 decimal places } catch (err) { - const errMessage = err instanceof Error ? err.message : String(err); + const errMessage = formatErrorMessage(err); throw new Error(`Failed to get audio duration: ${errMessage}`, { cause: err }); } } diff --git a/extensions/slack/src/draft-stream.ts b/extensions/slack/src/draft-stream.ts index 14962982665..52a19f1bb90 100644 --- a/extensions/slack/src/draft-stream.ts +++ b/extensions/slack/src/draft-stream.ts @@ -1,4 +1,5 @@ import { createDraftStreamLoop } from "openclaw/plugin-sdk/channel-lifecycle"; +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { deleteSlackMessage, editSlackMessage } from "./actions.js"; import { SLACK_TEXT_LIMIT } from "./limits.js"; import { sendMessageSlack } from "./send.js"; @@ -80,9 +81,7 @@ export function createSlackDraftStream(params: { params.onMessageSent?.(); } catch (err) { stopped = true; - params.warn?.( - `slack stream preview failed: ${err instanceof Error ? err.message : String(err)}`, - ); + params.warn?.(`slack stream preview failed: ${formatErrorMessage(err)}`); } }; const loop = createDraftStreamLoop({ @@ -113,9 +112,7 @@ export function createSlackDraftStream(params: { accountId: params.accountId, }); } catch (err) { - params.warn?.( - `slack stream preview cleanup failed: ${err instanceof Error ? err.message : String(err)}`, - ); + params.warn?.(`slack stream preview cleanup failed: ${formatErrorMessage(err)}`); } }; diff --git a/extensions/slack/src/scopes.ts b/extensions/slack/src/scopes.ts index fc7e14d741b..6d4aaa8de43 100644 --- a/extensions/slack/src/scopes.ts +++ b/extensions/slack/src/scopes.ts @@ -1,4 +1,5 @@ import type { WebClient } from "@slack/web-api"; +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { isRecord } from "openclaw/plugin-sdk/text-runtime"; import { createSlackWebClient } from "./client.js"; @@ -84,7 +85,7 @@ async function callSlack( } catch (err) { return { ok: false, - error: err instanceof Error ? err.message : String(err), + error: formatErrorMessage(err), }; } } diff --git a/extensions/telegram/src/audit-membership-runtime.ts b/extensions/telegram/src/audit-membership-runtime.ts index 378835b72e1..25feaf487ba 100644 --- a/extensions/telegram/src/audit-membership-runtime.ts +++ b/extensions/telegram/src/audit-membership-runtime.ts @@ -1,3 +1,4 @@ +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { isRecord } from "openclaw/plugin-sdk/text-runtime"; import { fetchWithTimeout } from "openclaw/plugin-sdk/text-runtime"; import type { @@ -60,7 +61,7 @@ export async function auditTelegramGroupMembershipImpl( chatId, ok: false, status: null, - error: err instanceof Error ? err.message : String(err), + error: formatErrorMessage(err), matchKey: chatId, matchSource: "id", }); diff --git a/extensions/telegram/src/bot/delivery.replies.ts b/extensions/telegram/src/bot/delivery.replies.ts index 89e8d626fa0..38c41318743 100644 --- a/extensions/telegram/src/bot/delivery.replies.ts +++ b/extensions/telegram/src/bot/delivery.replies.ts @@ -740,7 +740,7 @@ export async function deliverReplies(params: { accountId: params.accountId, content: contentForSentHook, success: false, - error: error instanceof Error ? error.message : String(error), + error: formatErrorMessage(error), isGroup: params.mirrorIsGroup, groupId: params.mirrorGroupId, }); diff --git a/extensions/telegram/src/channel.ts b/extensions/telegram/src/channel.ts index 37c4d85ea23..bbac5494be2 100644 --- a/extensions/telegram/src/channel.ts +++ b/extensions/telegram/src/channel.ts @@ -16,6 +16,7 @@ import { } from "openclaw/plugin-sdk/channel-status"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; import { createChannelDirectoryAdapter } from "openclaw/plugin-sdk/directory-runtime"; +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { resolveOutboundSendDep, type OutboundSendDeps, @@ -542,7 +543,7 @@ async function resolveTelegramTargets(params: { return { input, resolved: false as const, - note: error instanceof Error ? error.message : String(error), + note: formatErrorMessage(error), }; } }), diff --git a/extensions/telegram/src/draft-stream.ts b/extensions/telegram/src/draft-stream.ts index cb249bbad53..ddffa165495 100644 --- a/extensions/telegram/src/draft-stream.ts +++ b/extensions/telegram/src/draft-stream.ts @@ -1,5 +1,6 @@ import type { Bot } from "grammy"; import { createFinalizableDraftLifecycle } from "openclaw/plugin-sdk/channel-lifecycle"; +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { buildTelegramThreadParams, type TelegramThreadSpec } from "./bot/helpers.js"; import { isSafeToRetrySendError, isTelegramClientRejection } from "./network-errors.js"; import { normalizeTelegramReplyToMessageId } from "./outbound-params.js"; @@ -362,9 +363,7 @@ export function createTelegramDraftStream(params: { return sent; } catch (err) { streamState.stopped = true; - params.warn?.( - `telegram stream preview failed: ${err instanceof Error ? err.message : String(err)}`, - ); + params.warn?.(`telegram stream preview failed: ${formatErrorMessage(err)}`); return false; } }; @@ -451,9 +450,7 @@ export function createTelegramDraftStream(params: { return streamMessageId; } } catch (err) { - params.warn?.( - `telegram stream preview materialize failed: ${err instanceof Error ? err.message : String(err)}`, - ); + params.warn?.(`telegram stream preview materialize failed: ${formatErrorMessage(err)}`); } return undefined; }; diff --git a/extensions/telegram/src/fetch.ts b/extensions/telegram/src/fetch.ts index fd3477621d1..ad8e951290c 100644 --- a/extensions/telegram/src/fetch.ts +++ b/extensions/telegram/src/fetch.ts @@ -1,5 +1,6 @@ import * as dns from "node:dns"; import type { TelegramNetworkConfig } from "openclaw/plugin-sdk/config-runtime"; +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { createPinnedLookup, hasEnvHttpProxyConfigured, @@ -270,7 +271,7 @@ function createTelegramDispatcher(policy: PinnedDispatcherPolicy): { effectivePolicy: policy, }; } catch (err) { - const reason = err instanceof Error ? err.message : String(err); + const reason = formatErrorMessage(err); throw new Error(`explicit proxy dispatcher init failed: ${reason}`, { cause: err }); } } @@ -293,9 +294,7 @@ function createTelegramDispatcher(policy: PinnedDispatcherPolicy): { }; } catch (err) { log.warn( - `env proxy dispatcher init failed; falling back to direct dispatcher: ${ - err instanceof Error ? err.message : String(err) - }`, + `env proxy dispatcher init failed; falling back to direct dispatcher: ${formatErrorMessage(err)}`, ); const directPolicy: PinnedDispatcherPolicy = { mode: "direct", diff --git a/extensions/telegram/src/probe.ts b/extensions/telegram/src/probe.ts index 03021b4044e..1deeb9ac8a2 100644 --- a/extensions/telegram/src/probe.ts +++ b/extensions/telegram/src/probe.ts @@ -1,5 +1,6 @@ import type { BaseProbeResult } from "openclaw/plugin-sdk/channel-contract"; import type { TelegramNetworkConfig } from "openclaw/plugin-sdk/config-runtime"; +import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { fetchWithTimeout } from "openclaw/plugin-sdk/text-runtime"; import { resolveTelegramApiBase, resolveTelegramFetch } from "./fetch.js"; import { makeProxyFetch } from "./proxy.js"; @@ -217,7 +218,7 @@ export async function probeTelegram( return { ...result, status: err instanceof Response ? err.status : result.status, - error: err instanceof Error ? err.message : String(err), + error: formatErrorMessage(err), elapsedMs: Date.now() - started, }; } diff --git a/extensions/telegram/src/send.ts b/extensions/telegram/src/send.ts index fd9d5bfe1fc..7db986639aa 100644 --- a/extensions/telegram/src/send.ts +++ b/extensions/telegram/src/send.ts @@ -1080,7 +1080,7 @@ export async function reactMessageTelegram( try { await requestWithDiag(() => api.setMessageReaction(chatId, messageId, reactions), "reaction"); } catch (err: unknown) { - const msg = err instanceof Error ? err.message : String(err); + const msg = formatErrorMessage(err); if (/REACTION_INVALID/i.test(msg)) { return { ok: false as const, warning: `Reaction unavailable: ${trimmedEmoji}` }; }