跳转至

errors

feishu.errors

FeishuError

Bases: Exception

所有飞书异常的基类。

封装飞书 API 返回的错误码、错误信息以及用于排查问题的链路追踪 ID(log_id), 同时保留原始响应体(raw)以便进一步分析。所有具体的异常类型都继承自该类, 因此 except FeishuError 可以捕获本库抛出的全部飞书相关异常。

参数:

名称 类型 描述 默认

code

int

飞书业务错误码,传输层错误固定为 -1

必需

message

str

人类可读的错误信息。

必需

log_id

str | None

飞书返回的链路追踪 ID,用于向飞书反馈问题时定位日志。

None

raw

Any

原始响应体(通常为 dict),便于排查未被归类的字段。

None
飞书文档

通用错误码

示例:

Python Console Session
1
2
3
4
5
6
7
>>> err = FeishuError(99991663, "bad token", log_id="lg-1", raw={"x": 1})
>>> err.code
99991663
>>> err.log_id
'lg-1'
>>> str(err)
"FeishuError(code=99991663, message='bad token', log_id='lg-1')"
源代码位于: feishu/errors.py
Python
class FeishuError(Exception):
    r"""
    所有飞书异常的基类。

    封装飞书 API 返回的错误码、错误信息以及用于排查问题的链路追踪 ID(log_id),
    同时保留原始响应体(raw)以便进一步分析。所有具体的异常类型都继承自该类,
    因此 `except FeishuError` 可以捕获本库抛出的全部飞书相关异常。

    Args:
        code: 飞书业务错误码,传输层错误固定为 `-1`。
        message: 人类可读的错误信息。
        log_id: 飞书返回的链路追踪 ID,用于向飞书反馈问题时定位日志。
        raw: 原始响应体(通常为 `dict`),便于排查未被归类的字段。

    飞书文档:
        [通用错误码](https://open.feishu.cn/document/server-docs/api-call-guide/generic-error-code)

    Examples:
        >>> err = FeishuError(99991663, "bad token", log_id="lg-1", raw={"x": 1})
        >>> err.code
        99991663
        >>> err.log_id
        'lg-1'
        >>> str(err)
        "FeishuError(code=99991663, message='bad token', log_id='lg-1')"
    """

    def __init__(self, code: int, message: str, *, log_id: str | None = None, raw: Any = None):  # noqa: B042
        super().__init__(message)
        self.code = code
        self.message = message
        self.log_id = log_id
        self.raw = raw

    def __str__(self) -> str:
        return f"{type(self).__name__}(code={self.code}, message={self.message!r}, log_id={self.log_id!r})"

FeishuAuthError

Bases: FeishuError

鉴权失败异常。

当令牌缺失、无效、过期或类型错误时抛出(例如 tenant_access_token 过期, 或 OAuth 授权码已失效)。一般通过刷新或重新获取令牌即可恢复。

飞书文档

通用错误码

示例:

Python Console Session
1
2
3
>>> err = FeishuAuthError(99991663, "invalid token")
>>> isinstance(err, FeishuError)
True
源代码位于: feishu/errors.py
Python
class FeishuAuthError(FeishuError):
    r"""
    鉴权失败异常。

    当令牌缺失、无效、过期或类型错误时抛出(例如 `tenant_access_token` 过期,
    或 OAuth 授权码已失效)。一般通过刷新或重新获取令牌即可恢复。

    飞书文档:
        [通用错误码](https://open.feishu.cn/document/server-docs/api-call-guide/generic-error-code)

    Examples:
        >>> err = FeishuAuthError(99991663, "invalid token")
        >>> isinstance(err, FeishuError)
        True
    """

FeishuPermissionError

Bases: FeishuAuthError

权限不足异常。

当应用或用户缺少接口所需的权限范围(scope)时抛出。这属于配置或授权问题 (需在开发者后台为应用申请权限,或引导用户重新授权),与令牌无效或过期不同。 该类继承自 feishu.errors.FeishuAuthError,因此 except FeishuAuthError 也能捕获权限错误。

飞书文档

通用错误码

示例:

Python Console Session
1
2
3
>>> err = FeishuPermissionError(99991672, "no scope")
>>> isinstance(err, FeishuAuthError)
True
源代码位于: feishu/errors.py
Python
class FeishuPermissionError(FeishuAuthError):
    r"""
    权限不足异常。

    当应用或用户缺少接口所需的权限范围(scope)时抛出。这属于配置或授权问题
    (需在开发者后台为应用申请权限,或引导用户重新授权),与令牌无效或过期不同。
    该类继承自 [feishu.errors.FeishuAuthError][],因此 `except FeishuAuthError`
    也能捕获权限错误。

    飞书文档:
        [通用错误码](https://open.feishu.cn/document/server-docs/api-call-guide/generic-error-code)

    Examples:
        >>> err = FeishuPermissionError(99991672, "no scope")
        >>> isinstance(err, FeishuAuthError)
        True
    """

FeishuApiError

Bases: FeishuError

通用业务错误异常。

当请求未命中限流、服务器错误或鉴权错误等特定分类,而是返回了普通的业务错误码 (例如参数非法、资源不存在、被拒绝)时抛出。

飞书文档

通用错误码

示例:

Python Console Session
1
2
3
>>> err = FeishuApiError(230002, "denied")
>>> err.code
230002
源代码位于: feishu/errors.py
Python
class FeishuApiError(FeishuError):
    r"""
    通用业务错误异常。

    当请求未命中限流、服务器错误或鉴权错误等特定分类,而是返回了普通的业务错误码
    (例如参数非法、资源不存在、被拒绝)时抛出。

    飞书文档:
        [通用错误码](https://open.feishu.cn/document/server-docs/api-call-guide/generic-error-code)

    Examples:
        >>> err = FeishuApiError(230002, "denied")
        >>> err.code
        230002
    """

FeishuServerError

Bases: FeishuError

飞书服务器错误异常。

对应 HTTP 500/502/503/504。这类错误通常是临时性的,传输层会自动重试; 若重试耗尽仍未恢复,则向调用方抛出该异常。

飞书文档

通用错误码

示例:

Python Console Session
1
2
3
>>> err = FeishuServerError(0, "unavailable")
>>> isinstance(err, FeishuError)
True
源代码位于: feishu/errors.py
Python
class FeishuServerError(FeishuError):
    r"""
    飞书服务器错误异常。

    对应 HTTP 500/502/503/504。这类错误通常是临时性的,传输层会自动重试;
    若重试耗尽仍未恢复,则向调用方抛出该异常。

    飞书文档:
        [通用错误码](https://open.feishu.cn/document/server-docs/api-call-guide/generic-error-code)

    Examples:
        >>> err = FeishuServerError(0, "unavailable")
        >>> isinstance(err, FeishuError)
        True
    """

FeishuRateLimitError

Bases: FeishuError

触发限流异常。

对应 HTTP 429 或限流错误码。传输层会先按 reset_after(若服务器提供) 自动退避重试;重试耗尽后向调用方抛出该异常。reset_after 表示建议的 重试等待秒数。

参数:

名称 类型 描述 默认

code

int

飞书业务错误码。

必需

message

str

人类可读的错误信息。

必需

log_id

str | None

飞书返回的链路追踪 ID。

None

raw

Any

原始响应体。

None

reset_after

float | None

建议的重试等待秒数,来源于 x-ogw-ratelimit-reset 响应头。

None
飞书文档

服务端 API 调用频率限制

示例:

Python Console Session
1
2
3
>>> err = FeishuRateLimitError(99991400, "slow", reset_after=2.0)
>>> err.reset_after
2.0
源代码位于: feishu/errors.py
Python
class FeishuRateLimitError(FeishuError):
    r"""
    触发限流异常。

    对应 HTTP 429 或限流错误码。传输层会先按 `reset_after`(若服务器提供)
    自动退避重试;重试耗尽后向调用方抛出该异常。`reset_after` 表示建议的
    重试等待秒数。

    Args:
        code: 飞书业务错误码。
        message: 人类可读的错误信息。
        log_id: 飞书返回的链路追踪 ID。
        raw: 原始响应体。
        reset_after: 建议的重试等待秒数,来源于 `x-ogw-ratelimit-reset` 响应头。

    飞书文档:
        [服务端 API 调用频率限制](https://open.feishu.cn/document/server-docs/api-call-guide/frequency-control)

    Examples:
        >>> err = FeishuRateLimitError(99991400, "slow", reset_after=2.0)
        >>> err.reset_after
        2.0
    """

    def __init__(  # noqa: B042
        self,
        code: int,
        message: str,
        *,
        log_id: str | None = None,
        raw: Any = None,
        reset_after: float | None = None,
    ) -> None:
        super().__init__(code, message, log_id=log_id, raw=raw)
        self.reset_after = reset_after

FeishuTransportError

Bases: FeishuError

传输层错误异常。

当 HTTP 请求本身失败(连接错误、超时等网络问题)且重试耗尽时抛出。 错误码固定为 -1,底层原始异常保留在 original 属性中以便排查。

参数:

名称 类型 描述 默认

message

str

人类可读的错误信息。

必需

original

BaseException | None

触发该错误的底层异常(通常为 httpx.RequestError)。

None

示例:

Python Console Session
1
2
3
4
5
6
>>> cause = ValueError("boom")
>>> err = FeishuTransportError("request failed: boom", original=cause)
>>> err.code
-1
>>> err.original is cause
True
源代码位于: feishu/errors.py
Python
class FeishuTransportError(FeishuError):
    r"""
    传输层错误异常。

    当 HTTP 请求本身失败(连接错误、超时等网络问题)且重试耗尽时抛出。
    错误码固定为 `-1`,底层原始异常保留在 `original` 属性中以便排查。

    Args:
        message: 人类可读的错误信息。
        original: 触发该错误的底层异常(通常为 `httpx.RequestError`)。

    Examples:
        >>> cause = ValueError("boom")
        >>> err = FeishuTransportError("request failed: boom", original=cause)
        >>> err.code
        -1
        >>> err.original is cause
        True
    """

    def __init__(self, message: str, *, original: BaseException | None = None):  # noqa: B042
        super().__init__(-1, message)
        self.original = original

FeishuSignatureError

Bases: FeishuError

Webhook 签名校验失败异常。

供需要严格的、基于抛异常的签名校验的调用方使用。注意:本库内置的 Starlette 接收器(create_event_route / create_card_route)在签名校验失败时返回 HTTP 401 响应,而不会抛出该异常。

飞书文档

配置订阅方式-加密

示例:

Python Console Session
1
2
3
>>> err = FeishuSignatureError(401, "signature mismatch")
>>> isinstance(err, FeishuError)
True
源代码位于: feishu/errors.py
Python
class FeishuSignatureError(FeishuError):
    r"""
    Webhook 签名校验失败异常。

    供需要严格的、基于抛异常的签名校验的调用方使用。注意:本库内置的 Starlette
    接收器(`create_event_route` / `create_card_route`)在签名校验失败时返回
    HTTP 401 响应,而不会抛出该异常。

    飞书文档:
        [配置订阅方式-加密](https://open.feishu.cn/document/server-docs/event-subscription-guide/event-subscription-configure-/request-url-configuration-case)

    Examples:
        >>> err = FeishuSignatureError(401, "signature mismatch")
        >>> isinstance(err, FeishuError)
        True
    """

FeishuCryptoError

Bases: FeishuError

事件解密失败异常。

feishu.events.crypto.decrypt 无法解密密文时抛出,例如加密密钥错误、 密文损坏或 PKCS#7 填充非法。

飞书文档

事件订阅概述-数据加密

示例:

Python Console Session
1
2
3
>>> err = FeishuCryptoError(-1, "bad padding", raw={"encrypt": "x"})
>>> err.code
-1
源代码位于: feishu/errors.py
Python
class FeishuCryptoError(FeishuError):
    r"""
    事件解密失败异常。

    当 `feishu.events.crypto.decrypt` 无法解密密文时抛出,例如加密密钥错误、
    密文损坏或 PKCS#7 填充非法。

    飞书文档:
        [事件订阅概述-数据加密](https://open.feishu.cn/document/server-docs/event-subscription-guide/event-subscription-configure-/encrypt-key-encryption-configuration-case)

    Examples:
        >>> err = FeishuCryptoError(-1, "bad padding", raw={"encrypt": "x"})
        >>> err.code
        -1
    """

error_from_envelope

Python
error_from_envelope(code: int, message: str, *, status: int, log_id: str | None, raw: Any, reset_after: float | None = None, error_description: str | None = None) -> FeishuError

依据 HTTP 状态码与响应体错误码,构造对应的具体异常实例。

分类顺序为:限流(429 或限流码)> 服务器错误(5xx)> 权限不足 > 鉴权失败 (鉴权错误码、401/403,或 OAuth invalid_* 等错误形态)> 通用业务错误。 错误描述优先取 error_description,其次取响应体中的 error_description / error,最后回退到 message

参数:

名称 类型 描述 默认

code

int

响应体中的业务错误码。

必需

message

str

响应体中的 msg 字段。

必需

status

int

HTTP 状态码。

必需

log_id

str | None

飞书返回的链路追踪 ID。

必需

raw

Any

原始响应体。

必需

reset_after

float | None

建议的重试等待秒数(用于限流错误)。

None

error_description

str | None

OAuth 风格响应中的错误描述,优先作为错误信息。

None

返回:

类型 描述
FeishuError

与状态码、错误码相匹配的 feishu.errors.FeishuError 子类实例。

示例:

Python Console Session
>>> err = error_from_envelope(99991400, "slow", status=429, log_id=None, raw={})
>>> type(err).__name__
'FeishuRateLimitError'
>>> err = error_from_envelope(0, "unavailable", status=503, log_id=None, raw={})
>>> type(err).__name__
'FeishuServerError'
>>> err = error_from_envelope(99991672, "no scope", status=200, log_id=None, raw={})
>>> type(err).__name__
'FeishuPermissionError'
>>> err = error_from_envelope(99991663, "bad token", status=200, log_id=None, raw={})
>>> type(err).__name__
'FeishuAuthError'
>>> err = error_from_envelope(230002, "denied", status=200, log_id=None, raw={})
>>> type(err).__name__
'FeishuApiError'
源代码位于: feishu/errors.py
Python
def error_from_envelope(
    code: int,
    message: str,
    *,
    status: int,
    log_id: str | None,
    raw: Any,
    reset_after: float | None = None,
    error_description: str | None = None,
) -> FeishuError:
    r"""
    依据 HTTP 状态码与响应体错误码,构造对应的具体异常实例。

    分类顺序为:限流(429 或限流码)> 服务器错误(5xx)> 权限不足 > 鉴权失败
    (鉴权错误码、401/403,或 OAuth `invalid_*` 等错误形态)> 通用业务错误。
    错误描述优先取 `error_description`,其次取响应体中的 `error_description` /
    `error`,最后回退到 `message`。

    Args:
        code: 响应体中的业务错误码。
        message: 响应体中的 `msg` 字段。
        status: HTTP 状态码。
        log_id: 飞书返回的链路追踪 ID。
        raw: 原始响应体。
        reset_after: 建议的重试等待秒数(用于限流错误)。
        error_description: OAuth 风格响应中的错误描述,优先作为错误信息。

    Returns:
        与状态码、错误码相匹配的 [feishu.errors.FeishuError][] 子类实例。

    Examples:
        >>> err = error_from_envelope(99991400, "slow", status=429, log_id=None, raw={})
        >>> type(err).__name__
        'FeishuRateLimitError'
        >>> err = error_from_envelope(0, "unavailable", status=503, log_id=None, raw={})
        >>> type(err).__name__
        'FeishuServerError'
        >>> err = error_from_envelope(99991672, "no scope", status=200, log_id=None, raw={})
        >>> type(err).__name__
        'FeishuPermissionError'
        >>> err = error_from_envelope(99991663, "bad token", status=200, log_id=None, raw={})
        >>> type(err).__name__
        'FeishuAuthError'
        >>> err = error_from_envelope(230002, "denied", status=200, log_id=None, raw={})
        >>> type(err).__name__
        'FeishuApiError'
    """
    text = error_description
    if not text and isinstance(raw, dict):
        text = raw.get("error_description") or raw.get("error")
    if not text:
        text = message or ""
    if code in RATE_LIMIT_CODES or status == 429:
        return FeishuRateLimitError(code, text, log_id=log_id, raw=raw, reset_after=reset_after)
    if status in SERVER_RETRY_STATUS:
        return FeishuServerError(code, text, log_id=log_id, raw=raw)
    if code in PERMISSION_ERROR_CODES:
        return FeishuPermissionError(code, text, log_id=log_id, raw=raw)
    if code in AUTH_ERROR_CODES or status in (401, 403) or (isinstance(raw, dict) and _is_auth_error(raw)):
        return FeishuAuthError(code, text, log_id=log_id, raw=raw)
    return FeishuApiError(code, text, log_id=log_id, raw=raw)