DEBUG.WIKI
雨云;给项目一台云服务器
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →
PanstarCloud:部署应用,接入 AI,云服务器与 AI 网关

Pydantic ValidationError 反序列化报 Invalid error type: sequence_str

部分 Pydantic 自定义错误可以被 pickle 写出,却在还原 ValidationError 时失败。跨进程传递稳定的错误数据,保留字段位置与错误类型,别把反序列化失败当成原校验失败。

工作进程已经捕获 ValidationError,把异常对象传回主进程时却出现 KeyError: "Invalid error type: 'sequence_str'"。这可能发生在 pickle.loads(pickle.dumps(exc)),而不是最初模型验证的位置。

Pydantic 2.14.1、core 2.50.1 的具体例子是 Sequence[str] 字段收到普通字符串。验证阶段产生 sequence_str 错误;pickle 写出异常时保存了错误数据,还原时再调用 from_exception_data(),某些自定义错误标识不能按普通内置错误名重建,于是又抛 KeyError。

传递错误数据,而不是要求恢复同一个异常对象

若调用方只是需要展示哪些字段失败,可以在捕获处建立明确的数据载体。下面省略输入值和上下文,避免把业务原文或异常对象塞进传输层:

from collections.abc import Sequence
from pydantic import BaseModel, ValidationError

class Item(BaseModel):
    names: Sequence[str]

try:
    Item(names="one")
except ValidationError as exc:
    failure = {
        "kind": "validation_error",
        "title": exc.title,
        "errors": exc.errors(
            include_url=False,
            include_context=False,
            include_input=False,
        ),
    }

failure 是应用自定的错误响应,不是新建的 ValidationError。接收方应按这个载体处理 loc、type 和 msg,而不是再次把错误字典交给 ValidationError.from_exception_data(),重走同一条失败路径。

若原接口必须抛异常,可以由传输层把载体包装成应用自己的稳定异常类型,保留原始错误类型与字段位置;这需要明确接口变化,不能让原来捕获 ValidationError 的调用方无声失效。

区分业务错误与错误传递失败

这里 Sequence[str] 拒绝普通字符串有实际含义:一整个字符串不应被当成名字列表。把字段改为 Any,或允许字符串逐字符拆开,只是改变输入约束,不能解决自定义错误的重建问题。

同样,不能看到 pickle 写入成功就认为进程通信正常。复核必须覆盖写出、还原和接收方实际读取,至少包含内置错误、sequence_str 以及项目自己的 PydanticCustomError。错误载体还应覆盖嵌套字段位置和应用需要保留的消息信息。

如果确实要跨进程恢复完整的 Pydantic 异常,需使用能正确保留这些错误类型的正式依赖组合,并逐类验证;当前不能把所有 ValidationError 一概视为可可靠往返。pickle 本身也只应用于可信数据,不能为这次故障新增不可信 pickle 的加载入口。