快速结论:这个报错发生在 LangChain 表达式中把不支持的对象通过 | 管道符接入 Runnable 链时,coerce_to_runnable 直接抛出 TypeError。优先检查被管道连接的对象是否为 Runnable、可调用对象或字典;如果是第三方自定义类的运算符重载未生效,这是 LangChain 的有意设计,并非需要修复的缺陷。
适用环境:LangChain core(langchain-core 包),Python 环境。Issue 中未提供具体 Python、CUDA、显卡版本信息。
最快修复方案:暂无确认的一步修复方案。官方明确表示不会修改 Runnable.__or__/__ror__ 的现有行为,这是有意保留的设计——选择保持抛出描述性 TypeError,而不是遵循 Python 数据模型返回 NotImplemented。
注意事项:此问题的核心结论是“不修复”。对于普通用户,应确保管道运算符右侧的对象是正确的 Runnable 类型;对于库开发者,不建议尝试“修复”此行为使其返回 NotImplemented,因为可能会导致 NumPy 等第三方库产生误导性错误信息,并丢失对常见错误的有用提示。
问题场景
在使用 LangChain 的 LCEL(LangChain Expression Language)时,用户尝试通过 | 管道运算符将一个第三方自定义类的实例(示例中是 Foreign 类)连接到 RunnableLambda 上。在 Python 数据模型下,当左侧对象(Runnable)的 __or__ 方法无法处理操作数时,应当返回 NotImplemented,以便 Python 解释器尝试右侧对象的反射方法 __ror__。用户期望 Foreign.__ror__ 被调用,但实际触发了 TypeError,因此认为这是一个潜在 bug,并质疑 LangChain 的行为不符合 Python 数据模型约定。
报错原文
Traceback (most recent call last):
File "C:\Projects\lagnchain_or\repo.py", line 12, in <module>
chain | Foreign()
~~~~~~^~~~~~~~~~~
File "C:\Projects\lagnchain_or\arch\langchain\libs\core\langchain_core\runnables\base.py", line 667, in __or__
return RunnableSequence(self, coerce_to_runnable(other))
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Projects\lagnchain_or\arch\langchain\libs\core\langchain_core\runnables\base.py", line 6652, in coerce_to_runnable
raise TypeError(msg)
TypeError: Expected a Runnable, callable or dict.Instead got an unsupported type: <class '__main__.Foreign'>
原因分析
根因在于 Runnable.__or__ / __ror__ 方法直接调用 coerce_to_runnable(other)。当 other 不是 Runnable 类型(或可调用对象、字典)时,coerce_to_runnable 会直接抛出 TypeError("Expected a Runnable, callable or dict..."),而不是返回 NotImplemented。根据 Python 数据模型,二元运算符的 dunder 方法如果无法处理操作数,应当返回 NotImplemented,让解释器尝试另一操作数的反射方法。因此 chain | Foreign() 从未调用 Foreign.__ror__。
这是 LangChain 的有意设计,而非缺陷。官方在 Issue 讨论中明确论证:如果改为返回 NotImplemented,在 LCEL 代码中常见操作数(如 NumPy 数组、embedding 向量)上会产生误导性的第三方错误信息,并且会丢失当前这种描述性很强的 TypeError(它能够明确提示用户“Expected a Runnable, callable or dict”),帮助排查将错误对象接入链的常见错误。
环境排查
- 确认 LangChain core 版本是否为最新稳定版(此问题未因版本升级而改变行为)。
- 检查接入管道运算符
|右侧的对象类型:是否为Runnable实例、可调用函数、或字典(dict)。 - 如果使用了 type checker(如 mypy strict 模式),请注意静态类型系统会假设
chain | Foreign()的类型为str(通过Foreign.__ror__),这与运行时实际行为不一致。
解决步骤
- 确认报错对象:检查正在通过
|连接的右侧对象,确认它确实是你期望连接的 Runnable 或可调用对象。 - 修正连接方式:如果连接的是第三方类实例,请检查该实例是否实现了 Runnable 接口,或先将它包装为
RunnableLambda/RunnablePassthrough等可运行类型。示例代码中,如果确实需要调用Foreign.__ror__,应显式调用该方法:Foreign().__ror__(chain),而不是依赖chain | Foreign()的隐式协议。 - 对于库开发者——不要尝试返回 NotImplemented:官方在 Issue 中明确论证并拒绝了这个方向的修复。一个已提交的 PR(#39077)曾实现该修改,但被关闭,维护者确认这个更改会带来更差的行为:会触发 NumPy 侧令人困惑的错误,并且丢失对常见错误的清晰提示。
- 对于库开发者——建议的贡献方式:官方向提出此 Issue 的用户建议,可以提交“文档补充 + 特征测试”,将这个行为明确记录为有意的设计选择,防止后续再次被误作为 bug 提交。
验证方法
运行原始触发代码,确认现在仍会得到预期的 TypeError: Expected a Runnable, callable or dict 错误——这是 LangChain 的预期行为。若要验证修正后的链条可以正常工作,请将右侧对象替换为合法的 Runnable 类型(如 RunnableLambda(lambda x: x)),并确认链条可以完整执行。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


