[Bug] iOS app: MCP (HTTP) tool calls fail on self-hosted server — message.update rejected by ZodError (error.type required, app omits it)

在 LobeChat iOS App(App Store 版本)上,对自托管 Docker 服务器( lobehub/lobehub:2.2.9 )发起 Streamable HTTP 类型的 MCP 工具调用时,工具调用无法执行。同样的 MCP 工具、同一账号、同一自托管服务器,在 Web 桌面浏

[Bug] iOS app: MCP (HTTP) tool calls fail on self-hosted server — message.update rejected by ZodError (error.type required, app omits it)

[Bug] iOS app: MCP (HTTP) tool calls fail on self-hosted server — message.update rejected by ZodError (error.type required, app omits it)

快速结论:该问题仅发生在 iOS App(React Native 客户端)上,调用 Streamable HTTP 类型的 MCP 工具时,客户端构建的 error 对象缺少必需的 error.type 字段,导致服务端 message.update 的 Zod 校验失败。Web 端(桌面/移动浏览器)不受影响。优先排查 iOS 客户端 MCP 工具错误处理路径中 type 字段的默认值是否被遗漏。

问题场景

在 LobeChat iOS App(App Store 版本)上,对自托管 Docker 服务器(lobehub/lobehub:2.2.9)发起 Streamable HTTP 类型的 MCP 工具调用时,工具调用无法执行。同样的 MCP 工具、同一账号、同一自托管服务器,在 Web 桌面浏览器和 Web 移动浏览器上正常工作。

报错原文

Error in tRPC handler (mobile) on path: message.update, type: mutation
Error [TRPCError]: [
  {
    "code": "invalid_union",
    "unionErrors": [
      { "issues": [ { "code": "invalid_type", "expected": "string", "received": "undefined",
        "path": ["value","error","type"], "message": "Required" } ], "name": "ZodError" },
      { "issues": [ { "code": "invalid_type", "expected": "number", "received": "undefined",
        "path": ["value","error","type"], "message": "Required" } ], "name": "ZodError" }
    ],
    "path": ["value","error","type"],
    "message": "Invalid input"
  }
]

原因分析

服务端 ChatMessageErrorSchema(定义在 packages/types/src/message/common/base.ts)中 type 字段是必需的,类型为 z.union([z.string(), z.number()]),没有 .optional()。iOS 客户端在 MCP 工具调用失败时构建的错误对象缺少 type 字段(type: undefined),导致 message.update 的 Zod 联合类型校验失败。Web 客户端可能走了不同的代码路径或遇到了不同的错误形状,恰好包含了 type 字段。

具体来说,MCP 工具错误构造路径中,错误对象是这样构建的:

{
  message: (mcpResult.error as any)?.message ?? 'MCP tool call failed',
  type: (mcpResult.error as any)?.type
}

mcpResult.error.typeundefined 时,type: undefined 违反了 Zod 联合类型的校验。虽然在 updateMessageError 中存在对缺失 type 使用 'ApplicationRuntimeError' 作为默认值的回退模式,但该回退并未应用在 MCP 错误处理路径中。

环境排查

  • 服务器版本:自托管 Docker lobehub/lobehub:2.2.9 或更高版本(Issue 基于此版本)
  • 客户端类型:iOS App(App Store 最新版本,2026-07-08 时)—— 仅 iOS 受影响
  • MCP 工具类型:Streamable HTTP 类型(可访问的公共 URL)
  • 登录方式:已启用 OIDC 登录
  • 依赖检查:packages/types/src/message/common/base.tsChatMessageErrorSchema.type 是否为必需字段(自 #9952 起一直为必需)

解决步骤

  1. 定位 iOS 客户端 MCP 工具错误构造路径。Issue 中确认了 MCP 工具调用失败时错误对象构建的位置。
  2. 在构建错误对象时,为 type 字段添加一个默认值回退,例如:type: (mcpResult.error as any)?.type ?? 'MCPToolCallError'
  3. 该修复方案与代码库中其他位置已有的防御性回退模式(updateMessageError 中默认使用 'ApplicationRuntimeError')保持一致。
  4. 备选方案:在服务端 ChatMessageErrorSchema 中使 type 字段变为可选(设置为 .optional()),并设定合理的默认值。但 Issue 指出目前 type 是唯一一个没有 .optional() 的字段,且从 #9952 起一直如此,因此客户端修复优先级更高。

验证方法

  1. 应用修复后,在 iOS App 上使用相同的自托管服务器和相同的 MCP 工具重复复现步骤。
  2. 确认服务端 message.update 不再报 ZodError,且 MCP 工具调用能正常执行并返回结果。
  3. 确认修复后 Web 端(桌面/移动浏览器)功能仍然正常,不受影响。
  4. 检查服务端日志,确认 toolExecution / callTool 日志正常出现,而不是仅出现 message.update 的错误日志。

参考来源

lobehub/lobe-chat #16861

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

celebrityanime
celebrityanime
文章: 12087

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注