Hmbown/CodeWhale · error · Error

Lark SDK client does not expose im message create API

Error message

Lark SDK client does not expose im message create API

What it means

sendReply() resolves the Lark message-create entry point through both the v1 layout (client.im.v1.message.create) and the legacy flat layout (client.im.message.create). If neither exists, the installed @larksuiteoapi/node-sdk is too old or does not expose the IM API, and the bridge refuses to send rather than failing obscurely later.

Source

Thrown at integrations/feishu-bridge/src/index.mjs:554

}

async function sendText(chatId, text) {
  // Try reply API first — keeps bot responses inside the same Feishu
  // thread/topic instead of spawning new standalone topics.
  // / 优先使用 reply API,确保 bot 回复留在话题群的同一条话题内。
  const state = await threadStore.getChat(chatId);
  const replyToMessageId = state?.replyToMessageId || null;

  const replyMessage =
    replyToMessageId
      ? client.im?.v1?.message?.reply?.bind(client.im.v1.message) ||
        client.im?.message?.reply?.bind(client.im.message)
      : null;
  const createMessage =
    client.im?.v1?.message?.create?.bind(client.im.v1.message) ||
    client.im?.message?.create?.bind(client.im.message);
  if (!createMessage) {
    throw new Error("Lark SDK client does not expose im message create API");
  }

  let canReply = Boolean(replyMessage);
  for (const chunk of splitMessage(text, config.maxReplyChars)) {
    const body = {
      msg_type: "text",
      content: JSON.stringify({ text: chunk })
    };
    if (canReply) {
      try {
        await replyMessage({
          path: { message_id: replyToMessageId },
          data: body
        });
        continue;
      } catch (error) {
        canReply = false;
        console.warn("Feishu reply API failed; falling back to message create", error);

View on GitHub (pinned to 8880682c63)

Solutions

  1. Upgrade the SDK: npm install @larksuiteoapi/node-sdk@latest in integrations/feishu-bridge
  2. Log Object.keys(client.im || {}) once to see which layout the SDK provides
  3. If pinned intentionally, write a small adapter exposing the expected shape instead of removing the check

Example fix

// before - capability discovered only when a message must be sent
const createMessage = client.im?.v1?.message?.create?.bind(client.im.v1.message) ||
  client.im?.message?.create?.bind(client.im.message);
if (!createMessage) throw new Error('Lark SDK client does not expose im message create API');

// after - fail fast at startup with the fix in the message
const createMessage = client.im?.v1?.message?.create?.bind(client.im.v1.message) ||
  client.im?.message?.create?.bind(client.im.message);
if (!createMessage) {
  throw new Error('Unsupported @larksuiteoapi/node-sdk: upgrade to a version exposing im.v1.message.create');
}
Defensive patterns

Strategy: type-guard

Validate before calling

const createMessage =
  client.im?.v1?.message?.create?.bind(client.im.v1.message) ||
  client.im?.message?.create?.bind(client.im.message);
if (!createMessage) {
  throw new Error('Unsupported @larksuiteoapi/node-sdk: upgrade to a version exposing im.v1.message.create');
}

Type guard

function larkCanSendMessage(client) {
  return typeof (client.im?.v1?.message?.create || client.im?.message?.create) === 'function';
}
// usage: if (!larkCanSendMessage(client)) failFastAtStartup();

Prevention

When it happens

Trigger: Running the bridge with an SDK version predating client.im.v1; a custom/mock client in tests that omits the im namespace; an SDK refactor that moved the message API.

Common situations: package-lock pinning an old @larksuiteoapi/node-sdk; wrapper clients stripping namespaces; breaking SDK majors.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/8f2e9d4293d5d13a. Report an issue: GitHub.