CherryHQ/cherry-studio · error · Error
${action} failed: ${unwrapped.msg || unwrapped.message || `c
Error message
${action} failed: ${unwrapped.msg || unwrapped.message || `code=${String(unwrapped.code)}`} What it means
Thrown by ensureFeishuSuccess() when a Feishu (Lark) API response envelope has a non-zero business code. Feishu returns HTTP 200 with {code,msg,data}; code 0 means success, anything else is a business error. The message concatenates the action label plus msg/message/code from the envelope. unwrapFeishuResponse also synthesizes code:-1 if the shape is unexpected.
Source
Thrown at src/main/ai/channels/adapters/feishu/FeishuAdapter.ts:91
typeof response === 'object' &&
'data' in response &&
response.data &&
typeof response.data === 'object' &&
'code' in response.data
) {
return response.data as FeishuApiResponse<T>
}
return { code: -1, msg: 'Unexpected Feishu API response' }
}
function ensureFeishuSuccess<T>(response: unknown, action: string): FeishuApiResponse<T> {
const unwrapped = unwrapFeishuResponse<T>(response)
if (unwrapped.code === 0) {
return unwrapped
}
throw new Error(`${action} failed: ${unwrapped.msg || unwrapped.message || `code=${String(unwrapped.code)}`}`)
}
/**
* Build a Feishu "post" message payload with markdown element.
* Feishu's post format with md tag renders markdown natively.
*/
function buildPostPayload(text: string): string {
return JSON.stringify({
zh_cn: {
content: [[{ tag: 'md', text }]]
}
})
}
const STREAMING_ELEMENT_ID = 'streaming_content'
/** Throttle interval for CardKit streaming updates (ms). */
const CARDKIT_THROTTLE_MS = 200View on GitHub (pinned to 726446b54c)
Solutions
- Read the embedded msg — Feishu error messages are specific (e.g. '230002 chat_id is invalid', '99991663 token is invalid', '230001 permission denied'). Map it to the matching fix.
- Verify the bot app has the required scopes (im:message, im:message:send_as_bot) and that it was added to the target group; re-add it if removed.
- If code=-1 with 'Unexpected Feishu API response', the SDK returned a non-envelope object — check the @larksuiteoapi/node-sdk version and that you are not passing an upload result (which is already unwrapped) into ensureFeishuSuccess.
- Refresh tenant_access_token (the SDK normally auto-refreshes; confirm appId/appSecret are correct so refresh can succeed).
Example fix
// before
throw new Error(`${action} failed: ${unwrapped.msg || unwrapped.message || `code=${String(unwrapped.code)}`}`)
// after — include code separately for programmatic matching and keep data for context
throw new Error(`${action} failed [code=${unwrapped.code}]: ${unwrapped.msg || unwrapped.message || 'unknown'}`, { cause: unwrapped }) Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the receive_id format before calling the IM API.
function isValidFeishuChatId(id: string): boolean {
return /^oc_[a-zA-Z0-9]+$/.test(id)
} Type guard
interface FeishuApiResponse<T> { code: number; msg?: string; message?: string; data?: T }
function isFeishuBusinessError(e: unknown): e is Error {
return e instanceof Error && /failed:/.test(e.message) && !e.message.includes('HTTP')
} Try / catch
try {
await feishu.sendMessage(chatId, text)
} catch (e) {
if (isFeishuBusinessError(e)) {
if (/invalid|not exist/.test(e.message)) return // drop message to deleted chat
if (/token/i.test(e.message)) await feishu.refreshToken()
}
throw e
} Prevention
- Confirm the bot is a member of the target chat and has im:message:send_as_bot scope before sending.
- Keep @larksuiteoapi/node-sdk on a tested version so the response envelope shape stays stable.
- Never route upload-endpoint results (already unwrapped) through ensureFeishuSuccess.
When it happens
Trigger: Any client.im.* call routed through ensureFeishuSuccess — e.g. sendRawMessage's client.im.message.create (line ~543), sendFile's image/file message.create (lines ~588/606) — where the resolved envelope code !== 0. Also fires when the SDK returns a non-envelope object, yielding the synthetic 'Unexpected Feishu API response' / code=-1.
Common situations: chat_id/receive_id is wrong or the bot was removed from the chat, tenant_access_token expired or app permissions (im:message:send_as_bot) not granted, post content JSON malformed, sending to a chat type not enabled for the app, or SDK version returning a shape the unwrap helper doesn't recognize.
Related errors
- Feishu rejected the image upload for "${file.filename}" (no
- Feishu rejected the file upload for "${file.filename}" (no f
- Feishu WebSocket connection failed: ${error instanceof Error
- Client is not connected
- Invalid JSON from Feishu registration API: ${text.slice(0, 2
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/af337c8c9a19d895.
Report an issue: GitHub.