MLflow 异常体系深度解析:从 MlflowException 到 RestException 的源码级指南
MLflow 异常体系深度解析从 MlflowException 到 RestException 的源码级指南【免费下载链接】mlflowThe open source AI engineering platform for agents, LLMs, and ML models. MLflow enables teams of all sizes to debug, evaluate, monitor, and optimize production-quality AI applications while controlling costs and managing access to models and data.项目地址: https://gitcode.com/GitHub_Trending/ml/mlflowmlflow.exceptions是 MLflow 面向外部操作Tracking、Model Registry、Gateway、Tracing 等统一抛出的异常模块。本篇以 mlflow.exceptions.rst 为骨架结合 mlflow/exceptions.py、mlflow/error_classification.py、mlflow/utils/rest_utils.py 与 tests/test_exceptions.py 源码完整梳理异常类的签名、error_code 映射表、序列化格式与 REST 链路中的真实调用方式帮助你写出健壮的错误处理代码并读懂 MLflow 的报错信息。一、模块概览一个异常、一套编码、三类用途mlflow.exceptions的核心设计可以概括为一个基类 一张编码表 若干语义子类一个基类MlflowException所有 MLflow 操作失败的通用异常一张编码表ERROR_CODE_TO_HTTP_STATUS把 protobuf 定义的ErrorCode枚举映射为 HTTP 状态码同时提供反向映射若干语义子类包括面向 REST 调用的RestException、面向 MLflow Project 执行的ExecutionException、面向配置缺失的MissingConfigException、面向非法 URL 的InvalidUrlException以及 Tracing 相关的异常族。文档中给出的基类签名为mlflow.exceptions.MlflowException(message, error_code1, **kwargs)其中error_code1正是 protobuf 枚举中INTERNAL_ERROR的取值。在 databricks.proto 中可以看到完整的枚举定义INTERNAL_ERROR 1、TEMPORARILY_UNAVAILABLE 2、BAD_REQUEST 4……而 1000 以上的取值是 MLflow 自定义的业务编码例如INVALID_PARAMETER_VALUE 1000、ENDPOINT_NOT_FOUND 1001、INVALID_STATE 1003、PERMISSION_DENIED 1004、CUSTOMER_UNAUTHORIZED 1006、REQUEST_LIMIT_EXCEEDED 1007、RESOURCE_CONFLICT 1008、NOT_IMPLEMENTED 1010、DATA_LOSS 1011、RESOURCE_ALREADY_EXISTS 3001、RESOURCE_DOES_NOT_EXIST 3002。这些常量由mlflow.protos.databricks_pb2导出业务代码中直接 import 即可。二、MlflowException构造参数与字段语义在 mlflow/exceptions.py 中MlflowException的实际构造签名比文档标注更丰富def __init__( self, message: str, error_code: int INTERNAL_ERROR, sqlstate: str | None None, error_class: str | None None, **kwargs, ):各参数含义如下参数类型默认值说明messagestr必填错误描述文本会进入序列化 JSON也会作为str(exception)的内容error_codeintINTERNAL_ERROR(1)来自databricks_pb2的错误码非法值会被回退为INTERNAL_ERRORsqlstatestrNone自动推导5 字符 SQLSTATE 编码用于可靠性看板分类错误error_classstrNone自动推导描述性错误类别名如SCHEMA_ENFORCEMENT_FAILED**kwargsdict空附加键值对会并入序列化 JSON 输出构造完成后的实例字段包括error_code字符串形式的ErrorCode.Name、message、error_class、sqlstate以及json_kwargs。默认的sqlstate与error_class推导链是优先使用显式传入值未传入时先由error_code推导error_class再由error_class推导sqlstate见 mlflow/error_classification.py 的注释说明。2.1 派生工厂方法 invalid_parameter_value对于最常见的参数非法场景模块提供了类方法MlflowException.invalid_parameter_value(message, sqlstateNone, error_classNone, **kwargs)等价于MlflowException(message, error_codeINVALID_PARAMETER_VALUE, ...)。在 tests/test_exceptions.py 中有对应验证默认自动推导出sqlstateKAM00、error_classINVALID_PARAMETER_VALUE也支持显式覆盖例如传入sqlstateKAM02, error_classPREDICTION_FUNCTION_FAILED。2.2 序列化与 HTTP 状态码def serialize_as_json(self): exception_dict {error_code: self.error_code, message: self.message} if self.sqlstate is not None: exception_dict[sqlstate] self.sqlstate if self.error_class is not None: exception_dict[error_class] self.error_class exception_dict.update(self.json_kwargs) return json.dumps(exception_dict) def get_http_status_code(self): return ERROR_CODE_TO_HTTP_STATUS.get(self.error_code, 500)serialize_as_json()输出形如{error_code: ..., message: ..., sqlstate: ..., error_class: ...}的 JSON 字符串**kwargs中的附加字段会合并进去get_http_status_code()依据ERROR_CODE_TO_HTTP_STATUS映射表返回 HTTP 状态码未知编码一律回退为 500。三、error_code 与 HTTP 状态码的完整映射mlflow/exceptions.py 维护了两张方向相反的表这是理解 MLflow 报错的关键ErrorCodeprotobufHTTP 状态码语义INTERNAL_ERROR/INVALID_STATE/DATA_LOSS500内部错误 / 非法状态 / 数据丢失NOT_IMPLEMENTED501功能未实现TEMPORARILY_UNAVAILABLE503临时不可用DEADLINE_EXCEEDED504超时REQUEST_LIMIT_EXCEEDED/RESOURCE_EXHAUSTED429请求 / 资源超限CANCELLED499客户端主动取消ABORTED/RESOURCE_CONFLICT/ALREADY_EXISTS409冲突 / 已存在NOT_FOUND/ENDPOINT_NOT_FOUND/RESOURCE_DOES_NOT_EXIST404资源不存在PERMISSION_DENIED403权限拒绝CUSTOMER_UNAUTHORIZED/UNAUTHENTICATED401未认证 / 未授权BAD_REQUEST/RESOURCE_ALREADY_EXISTS/INVALID_PARAMETER_VALUE400请求错误 / 参数非法反向表HTTP_STATUS_TO_ERROR_CODE将 HTTP 码映射回 ErrorCode并额外处理了三种歧义400 固定为BAD_REQUEST、404 固定为ENDPOINT_NOT_FOUND、500 固定为INTERNAL_ERROR因为一个 HTTP 码可能对应多个 ErrorCode。模块级函数get_error_code(http_status)正是基于该反向表把未知 HTTP 状态兜底为INTERNAL_ERROR。这些行为在 tests/test_exceptions.py 中被逐一断言ENDPOINT_NOT_FOUND - 404、INVALID_PARAMETER_VALUE - 400、RESOURCE_ALREADY_EXISTS - 400未收录的编码如IO_ERROR也稳定回退为 500。四、错误分类体系sqlstate 与 error_class 的推导规则MLflow 近期的版本为异常引入了结构化分类能力实现在 mlflow/error_classification.pyerror_class比 error_code 更细粒度的分类如SCHEMA_ENFORCEMENT_FAILED、ATTRIBUTE_NOT_FOUND、MODEL_SERIALIZATION_FAILED、PREDICTION_FUNCTION_FAILED未显式指定时由 error_code 自动推导sqlstate5 字符编码供可靠性看板聚合错误未显式指定时先按 error_class、再按 error_code 推导。分类命名空间分客户端与服务端两套客户端错误使用KAM0x/XXM0x例如KAM00非法参数、KAM01schema 强制失败、KAM04属性未找到、XXM00客户端内部错误服务端CP/server使用KAMCx/XXMCx例如KAMC1权限拒绝、KAMC2资源不存在、KAMC4非法参数、XXMC0内部错误。二者互不混淆RestException构造时会根据来源自动选择 CP 映射。从 tests/test_exceptions.py 可确认推导结果默认构造MlflowException(test)得到sqlstateXXM00、error_classCLIENT_INTERNAL_ERROR显式传入sqlstateKAM01, error_classSCHEMA_ENFORCEMENT_FAILED时按显式值输出而对IO_ERROR这类未收录编码sqlstate与error_class均为None序列化 JSON 中也不会出现这两个字段。使用建议绝大多数 raise 点无需手动传sqlstate或error_class二者都会由 error_code 自动推导只有当 error_code 过粗、无法区分具体失败模式时例如同一个INVALID_PARAMETER_VALUE既用于 schema 强制失败又用于属性查找失败才显式传入error_classsqlstate则始终由 error_class 推导不建议直接传值。五、RestExceptionREST API 非 200 响应的统一异常RestException(MlflowException)的定位是REST API 返回非 200 级响应时抛出的异常构造函数接收服务端返回的 JSON 字典class RestException(MlflowException): def __init__(self, json): self.json json error_code json.get(error_code) or ErrorCode.Name(INTERNAL_ERROR) message {}: {}.format(error_code, json[message] if message in json else Response: str(json)) # 尝试解析 error_code若为 HTTP 码则经 HTTP_STATUS_TO_ERROR_CODE 转换 # 无法识别的编码记录 warning 并回退到 INTERNAL_ERROR ... # 从响应体保留 sqlstate/error_class缺失时按 CP 映射推导它的容错能力体现在三个兜底路径均有测试覆盖缺失/空 error_code回退为INTERNAL_ERRORtests/test_exceptions.pyerror_code 是 HTTP 状态码如403经HTTP_STATUS_TO_ERROR_CODE转换为PERMISSION_DENIEDtests/test_exceptions.py完全无法识别的编码记录logger.warning提示错误可能发生在到达 MLflow server 之前的代理或认证服务中并以INTERNAL_ERROR构造tests/test_exceptions.py。此外RestException通过重写__reduce__返回(RestException, (self.json,))使自己可被 pickle 序列化便于跨进程传播tests/test_exceptions.py。5.1 REST 链路中的真实调用点在 mlflow/utils/rest_utils.py 中http_request_safe()包装http_request()并调用verify_rest_response()校验响应状态码等于expected_status默认 200时正常返回状态码不符时若响应体可解析为 JSON 字典则raise RestException(json.loads(response.text))把服务端错误原样封装若响应体不是合法 JSON则用get_error_code(response.status_code)推导编码并显式带上 CP 侧的sqlstate/error_class构造MlflowException例如API request to endpoint ... failed with error code 404 ! 200。因此客户端捕获到的RestException.error_code、sqlstate、error_class很可能直接来自服务端序列化后的 JSON见 tests/test_exceptions.py 中保留服务端 sqlstate、忽略空值的断言。理解这一链路排查代理/网关返回的 502、504这类非 MLflow 错误时就能一眼识别 warning 日志的含义。六、其余异常子类一览异常类触发场景ExecutionExceptionMLflow Project 执行失败时抛出见 mlflow/exceptions.pyMissingConfigException期望的配置文件 / 目录未找到时抛出mlflow/exceptions.pyInvalidUrlException因 URL 非法导致 HTTP 请求发送失败时抛出mlflow/exceptions.py_UnsupportedMultipartUploadException/_UnsupportedMultipartDownloadException当前 artifact 仓库不支持分段上传 / 下载固定以NOT_IMPLEMENTED抛出mlflow/exceptions.py_UnsupportedPresignedUploadException/_UnsupportedPresignedDownloadException当前 artifact 仓库不支持预签名上传 / 下载固定以NOT_IMPLEMENTED抛出mlflow/exceptions.pyMlflowTracingExceptionTracing 逻辑内部错误。由于 Tracing 原则上不应阻塞主执行流此异常用于区分并妥善处理 Tracing 相关错误mlflow/exceptions.pyMlflowTraceDataExceptionTrace 数据相关错误依据NOT_FOUND/INVALID_STATE生成 Trace data not found / corrupted for request_id... 消息mlflow/exceptions.pyMlflowTraceDataNotFound/MlflowTraceDataCorrupted分别对应 Trace 数据未找到与数据损坏是上者的两个便捷子类mlflow/exceptions.pyMlflowTraceArchivalMalformedTraceTrace 归档序列化发现畸形内容以INVALID_PARAMETER_VALUE抛出mlflow/exceptions.pyMlflowNotImplementedException功能未实现固定以NOT_IMPLEMENTED抛出消息默认为空mlflow/exceptions.py注意以单下划线开头的_Unsupported*四个类是模块私有实现不对外承诺 API 稳定性其余类均可从mlflow.exceptions直接导入使用。七、在业务代码中的典型用法7.1 捕获并读取错误信息import mlflow from mlflow.exceptions import MlflowException, RestException try: mlflow.search_runs(experiment_ids[not_exist]) except RestException as e: # e.error_code 为服务端返回的 ErrorCode 字符串如 RESOURCE_DOES_NOT_EXIST # e.sqlstate / e.error_class 为服务端分类缺失时按 CP 映射推导 print(e.error_code, e.message, e.get_http_status_code()) except MlflowException as e: # 客户端本地操作失败error_code 默认 INTERNAL_ERROR print(e.error_code, e.serialize_as_json())7.2 按状态码做分支处理from mlflow.exceptions import MlflowException from mlflow.protos.databricks_pb2 import NOT_FOUND, PERMISSION_DENIED, REQUEST_LIMIT_EXCEEDED try: run_operation() except MlflowException as e: if e.error_code NOT_FOUND: pass # 资源不存在执行重建逻辑 elif e.error_code PERMISSION_DENIED: pass # 检查凭据与权限 elif e.error_code REQUEST_LIMIT_EXCEEDED: pass # 被限流建议退避重试7.3 抛出规范异常自定义扩展 / 插件开发from mlflow.exceptions import MlflowException, MlflowNotImplementedException from mlflow.protos.databricks_pb2 import RESOURCE_DOES_NOT_EXIST # 带业务错误码 raise MlflowException( experiment x does not exist, error_codeRESOURCE_DOES_NOT_EXIST, # 可选显式补充细粒度分类其余字段自动推导 error_classRESOURCE_NOT_FOUND, ) # 参数非法快捷方式 raise MlflowException.invalid_parameter_value(batch_size must be positive) # 未实现功能 raise MlflowNotImplementedException(custom endpoint is not supported yet)7.4 安全提示MlflowException的 message 可能被直接暴露在 HTTP 响应中供客户端调试。若错误文本涉及敏感信息源码注释明确建议改用普通Exception见 mlflow/exceptions.py避免敏感信息随 REST 响应外泄。八、写在最后排查错误的三个切入点看 error_code它决定 HTTP 状态码见第三节映射表先确认是 4xx客户端问题还是 5xx服务端问题看 error_class / sqlstate若出现KAM01/SCHEMA_ENFORCEMENT_FAILED这类细粒度编码说明错误发生在具体业务校验如模型 schema 强制阶段比 error_code 更能定位根因看 RestException 的来源当遇到无法识别的 error_code 时warning 日志提示请求可能在到达 MLflow server 前就被代理或认证服务拦截此时应检查中间链路而非 MLflow 本身。以上结论均可对照 mlflow/exceptions.py、mlflow/error_classification.py、mlflow/utils/rest_utils.py 与 tests/test_exceptions.py 复现验证API 文档原文见 mlflow.exceptions.rst。【免费下载链接】mlflowThe open source AI engineering platform for agents, LLMs, and ML models. MLflow enables teams of all sizes to debug, evaluate, monitor, and optimize production-quality AI applications while controlling costs and managing access to models and data.项目地址: https://gitcode.com/GitHub_Trending/ml/mlflow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考