Files
AstrBot/src-new/astrbot_sdk/docs/api/errors.md
whatevertogo a6acc3df36 Add comprehensive API documentation for types and utilities in AstrBot SDK
- Introduced `types.md` detailing type aliases, generics, and Pydantic models used in the SDK.
- Added `utils.md` covering utility classes and functions including CancelToken, MessageSession, command groups, and session management.
- Included usage examples and detailed descriptions for each component to enhance developer understanding and ease of use.
2026-03-17 02:06:18 +08:00

14 KiB
Raw Blame History

错误处理 API 完整参考

概述

AstrBot SDK 提供了统一的错误处理机制,支持跨进程传递错误信息。所有可预期的错误都应使用 AstrBotError 类或其工厂方法创建。

模块路径: astrbot_sdk.errors


目录


导入方式

# 从主模块导入
from astrbot_sdk import AstrBotError

# 从 errors 模块导入
from astrbot_sdk.errors import AstrBotError, ErrorCodes

错误处理流程

# 1. 抛出错误
raise AstrBotError.invalid_input("参数不能为空")

# 2. 错误被捕获并序列化为 payload
# 3. 跨进程传输后反序列化
# 4. 在 on_error 钩子中统一处理
class MyPlugin(Star):
    async def on_error(self, error: AstrBotError) -> None:
        if error.retryable:
            # 可重试的错误
            ctx.logger.warning(f"可重试错误: {error.message}")
        else:
            # 不可重试的错误
            ctx.logger.error(f"错误: {error.hint or error.message}")

ErrorCodes - 错误码常量

稳定的错误码常量,用于标识不同类型的错误。

定义

class ErrorCodes:
    """AstrBot v4 的稳定错误码常量。"""

错误码列表

不可重试错误retryable=False

错误码 说明 默认提示
UNKNOWN_ERROR 未知错误 -
LLM_NOT_CONFIGURED LLM 未配置 -
CAPABILITY_NOT_FOUND 能力未找到 请确认 AstrBot Core 是否已注册该 capability
PERMISSION_DENIED 权限被拒绝 -
LLM_ERROR LLM 错误 -
INVALID_INPUT 输入无效 请检查调用参数
CANCELLED 调用被取消 -
PROTOCOL_VERSION_MISMATCH 协议版本不匹配 请升级 astrbot_sdk 至最新版本
PROTOCOL_ERROR 协议错误 请检查通信双方的协议实现
INTERNAL_ERROR 内部错误 请联系插件作者
RATE_LIMITED 速率限制 操作过于频繁,请稍后再试
COOLDOWN_ACTIVE 冷却中 -

可重试错误retryable=True

错误码 说明 默认提示
CAPABILITY_TIMEOUT 能力调用超时 -
NETWORK_ERROR 网络错误 网络请求失败,请稍后重试
LLM_TEMPORARY_ERROR LLM 临时错误 -

AstrBotError - 错误类

AstrBot SDK 的标准错误类型,支持跨进程传递。

类定义

@dataclass(slots=True)
class AstrBotError(Exception):
    code: str
    message: str
    hint: str = ""
    retryable: bool = False
    docs_url: str = ""
    details: dict[str, Any] | None = None

属性说明

属性 类型 说明
code str 错误码,来自 ErrorCodes 常量
message str 错误消息,面向开发者
hint str 用户提示,面向终端用户
retryable bool 是否可重试
docs_url str 文档链接
details dict[str, Any] | None 详细信息

工厂方法

cancelled(message)

创建取消错误。

@classmethod
def cancelled(cls, message: str = "调用被取消") -> AstrBotError

参数:

  • message (str): 错误消息

返回: AstrBotError 实例

示例:

raise AstrBotError.cancelled("用户取消操作")

capability_not_found(name)

创建能力未找到错误。

@classmethod
def capability_not_found(cls, name: str) -> AstrBotError

参数:

  • name (str): 未找到的能力名称

返回: AstrBotError 实例

示例:

raise AstrBotError.capability_not_found("my_plugin.custom_capability")

invalid_input(message, *, hint, docs_url, details)

创建输入无效错误。

@classmethod
def invalid_input(
    cls,
    message: str,
    *,
    hint: str = "请检查调用参数",
    docs_url: str = "",
    details: dict[str, Any] | None = None,
) -> AstrBotError

参数:

  • message (str): 详细错误消息
  • hint (str): 用户提示,默认 "请检查调用参数"
  • docs_url (str): 文档链接
  • details (dict[str, Any] | None): 详细信息

返回: AstrBotError 实例

示例:

raise AstrBotError.invalid_input(
    "参数格式错误",
    hint="请使用 JSON 格式",
    details={"expected": "json", "received": "text"}
)

protocol_version_mismatch(message)

创建协议版本不匹配错误。

@classmethod
def protocol_version_mismatch(cls, message: str) -> AstrBotError

参数:

  • message (str): 详细错误消息

返回: AstrBotError 实例

示例:

raise AstrBotError.protocol_version_mismatch("SDK 版本 4.0 与 Core 版本 3.9 不兼容")

protocol_error(message)

创建协议错误。

@classmethod
def protocol_error(cls, message: str) -> AstrBotError

参数:

  • message (str): 详细错误消息

返回: AstrBotError 实例

示例:

raise AstrBotError.protocol_error("无效的 payload 格式")

internal_error(message, *, hint, docs_url, details)

创建内部错误。

@classmethod
def internal_error(
    cls,
    message: str,
    *,
    hint: str = "请联系插件作者",
    docs_url: str = "",
    details: dict[str, Any] | None = None,
) -> AstrBotError

参数:

  • message (str): 详细错误消息
  • hint (str): 用户提示,默认 "请联系插件作者"
  • docs_url (str): 文档链接
  • details (dict[str, Any] | None): 详细信息

返回: AstrBotError 实例

示例:

raise AstrBotError.internal_error(
    "处理逻辑异常",
    hint="请检查日志并联系插件作者",
    details={"traceback": "..."}
)

network_error(message, *, hint, docs_url, details)

创建网络错误。

@classmethod
def network_error(
    cls,
    message: str,
    *,
    hint: str = "网络请求失败,请稍后重试",
    docs_url: str = "",
    details: dict[str, Any] | None = None,
) -> AstrBotError

参数:

  • message (str): 详细错误消息
  • hint (str): 用户提示,默认 "网络请求失败,请稍后重试"
  • docs_url (str): 文档链接
  • details (dict[str, Any] | None): 详细信息

返回: AstrBotError 实例

特性: retryable=True

示例:

raise AstrBotError.network_error(
    "连接超时",
    hint="网络不稳定,请稍后重试",
    details={"url": "...", "timeout": 30}
)

rate_limited(*, hint, details)

创建速率限制错误。

@classmethod
def rate_limited(
    cls,
    *,
    hint: str = "操作过于频繁,请稍后再试。",
    details: dict[str, Any] | None = None,
) -> AstrBotError

参数:

  • hint (str): 用户提示,默认 "操作过于频繁,请稍后再试。"
  • details (dict[str, Any] | None): 详细信息

返回: AstrBotError 实例

特性: retryable=False

示例:

raise AstrBotError.rate_limited(
    hint="每分钟最多调用 5 次",
    details={"limit": 5, "window": 60, "remaining": 0}
)

cooldown_active(*, hint, details)

创建冷却中错误。

@classmethod
def cooldown_active(
    cls,
    *,
    hint: str,
    details: dict[str, Any] | None = None,
) -> AstrBotError

参数:

  • hint (str): 用户提示
  • details (dict[str, Any] | None): 详细信息

返回: AstrBotError 实例

特性: retryable=False

示例:

raise AstrBotError.cooldown_active(
    hint="技能冷却中,还需等待 25 秒",
    details={"cooldown": 30, "remaining": 25}
)

实例方法

to_payload()

序列化为可传输的字典格式,用于跨进程传递错误信息。

def to_payload(self) -> dict[str, object]

返回: dict[str, object] - 包含错误信息的字典

返回格式:

{
    "code": "invalid_input",
    "message": "参数格式错误",
    "hint": "请使用 JSON 格式",
    "retryable": False,
    "docs_url": "",
    "details": {"expected": "json", "received": "text"}
}

from_payload(payload)

从字典反序列化错误实例。

@classmethod
def from_payload(cls, payload: dict[str, object]) -> AstrBotError

参数:

  • payload (dict[str, object]): 包含错误信息的字典

返回: AstrBotError 实例

示例:

payload = error.to_payload()
restored_error = AstrBotError.from_payload(payload)

__str__()

返回错误消息。

def __str__(self) -> str

返回: str - message 属性的值


使用示例

基本错误处理

from astrbot_sdk import AstrBotError
from astrbot_sdk.errors import ErrorCodes

@on_command("divide")
async def divide(self, event: MessageEvent, a: int, b: int):
    if b == 0:
        raise AstrBotError.invalid_input(
            "除数不能为零",
            hint="请输入非零的除数"
        )
    return event.plain_result(f"{a} / {b} = {a / b}")

带详细信息的错误

@on_command("search")
async def search(self, event: MessageEvent, keyword: str):
    if not keyword or len(keyword.strip()) == 0:
        raise AstrBotError.invalid_input(
            "搜索关键词不能为空",
            hint="请输入要搜索的关键词",
            details={
                "field": "keyword",
                "constraint": "non_empty",
                "provided": keyword
            }
        )
    # 执行搜索...

捕获和处理错误

@on_command("risky")
async def risky_operation(self, event: MessageEvent):
    try:
        result = await some_network_request()
        return event.plain_result(f"成功: {result}")
    except AstrBotError as e:
        ctx.logger.error(f"操作失败: {e.message}")
        if e.retryable:
            await event.reply(f"操作失败(可重试): {e.hint or e.message}")
        else:
            await event.reply(f"操作失败: {e.hint or e.message}")

在插件中处理错误

class MyPlugin(Star):
    async def on_error(self, error: AstrBotError) -> None:
        """统一处理插件中的所有错误"""
        if error.code == ErrorCodes.CAPABILITY_NOT_FOUND:
            self.logger.error(f"能力未找到: {error.message}")
        elif error.code == ErrorCodes.NETWORK_ERROR:
            self.logger.warning(f"网络错误: {error.message}")
        elif error.retryable:
            self.logger.warning(f"可重试错误: {error.code} - {error.message}")
        else:
            self.logger.error(f"错误: {error.code} - {error.message}")

检查特定错误码

try:
    await some_capability_call()
except AstrBotError as e:
    if e.code == ErrorCodes.RATE_LIMITED:
        remaining = e.details.get("remaining", 0)
        await event.reply(f"请求过多,请稍后再试。剩余次数: {remaining}")
    elif e.code == ErrorCodes.CAPABILITY_TIMEOUT:
        await event.reply("请求超时,请稍后重试")
    else:
        await event.reply(f"错误: {e.hint or e.message}")

自定义错误(使用通用构造方法)

# 使用通用构造方法创建自定义错误
error = AstrBotError(
    code="custom_error_code",
    message="自定义错误消息",
    hint="这是给用户的提示",
    retryable=False,
    details={"custom_field": "custom_value"}
)
raise error

最佳实践

1. 使用工厂方法而非直接构造

# 推荐
raise AstrBotError.invalid_input("参数错误")

# 不推荐(除非需要自定义错误码)
raise AstrBotError(
    code=ErrorCodes.INVALID_INPUT,
    message="参数错误",
    hint="请检查调用参数"
)

2. 提供用户友好的提示

# 推荐
raise AstrBotError.invalid_input(
    "参数 'count' 必须为正整数",
    hint="请输入大于 0 的数字"
)

# 不推荐
raise AstrBotError.invalid_input("参数错误")

3. 使用 details 提供调试信息

raise AstrBotError.invalid_input(
    "参数验证失败",
    hint="请检查输入格式",
    details={
        "field": "email",
        "pattern": "^[\\w\\.-]+@[\\w\\.-]+\\.\\w+$",
        "provided": "invalid-email"
    }
)

4. 区分可重试和不可重试错误

# 网络错误 - 可重试
raise AstrBotError.network_error("连接失败")

# 参数错误 - 不可重试
raise AstrBotError.invalid_input("参数类型错误")

5. 在 on_error 中集中处理

class MyPlugin(Star):
    async def on_error(self, error: AstrBotError) -> None:
        # 记录所有错误
        self.logger.error(f"错误: [{error.code}] {error.message}")

        # 可重试错误记录为警告级别
        if error.retryable:
            self.logger.warning(f"可重试错误,考虑实现重试逻辑")

        # 特定错误码的特殊处理
        if error.code == ErrorCodes.CAPABILITY_NOT_FOUND:
            self.logger.critical("请检查 AstrBot Core 配置")

6. 向用户展示适当的错误信息

try:
    result = await operation()
except AstrBotError as e:
    # 优先使用 hint面向用户
    user_message = e.hint or e.message
    await event.reply(user_message)

    # 记录完整的错误信息(面向开发者)
    ctx.logger.error(f"操作失败: {e.code} - {e.message}", extra=e.details)

相关模块

  • 事件处理: astrbot_sdk.events.MessageEvent
  • 上下文: astrbot_sdk.context.Context
  • 插件基类: astrbot_sdk.star.Star

版本: v4.0 模块: astrbot_sdk.errors 最后更新: 2026-03-17