错误处理
AI 友好的错误处理架构需要 @lovrabet/sdk v1.2.5 及以上版本。
Lovrabet SDK 采用 AI 友好的错误处理架构,专为 Vibe Coding(AI 辅助编程)场景设计。当你在 Cursor、Claude Code、Copilot 等 AI 编程工具中使用 SDK 时,错误信息能够被 AI 直接理解,并自动提供修复建议。
设计理念
为什么需要 AI 友好的错误?
传统的错误处理只关注人类开发者:
// 传统错误 - AI 难以理解上下文
Error: "project_id列不能为空"
在 Vibe Coding 场景下,AI 需要更多上下文才能帮你修复问题:
- 这是什么类型的错误?参数错误?权限问题?
- 具体是哪个字段出了问题?
- 应该如何修复?有什么建议?
- 如何获取正确的字段信息?
Lovrabet SDK 的 AI 友好架构正是为解决这些问题而设计。
架构目标
- 错误可被 AI 理解 - 结构化的错误信息,包含错误类型、原因、状态码
- 提供修复建议 - 针对不同错误类型,给出具体的修复方向
- 引导 AI 使用工具 - 当需要更多信息时,引导 AI 调用 MCP 工具获取
- 支持自动修复 - AI 可以根据建议自动修改代码
LovrabetError 类型
SDK 所有错误都使用统一的 LovrabetError 类型抛出:
import { LovrabetError } from "@lovrabet/sdk";
try {
await client.models.users.create({ name: "张三" });
} catch (error) {
if (error instanceof LovrabetError) {
console.log(error.message); // 错误消息
console.log(error.code); // 错误码
console.log(error.status); // HTTP 状态码
console.log(error.description); // AI 友好的详细描述 ⭐
console.log(error.response); // 服务端原始响应
console.log(error.cause); // 原始错误(v1.2.10+)
}
}
错误属性详解
| 属性 | 类型 | 用途 | AI 如何使用 |
|---|---|---|---|
message | string | 简短错误消息 | 快速了解问题 |
code | string | 错误码 | 判断错误类别 |
status | number | HTTP 状态码 | 判断是客户端还是服务端问题 |
description | string | AI 友好的详细描述 | 理解错误原因、获取修复建议 |
response | object | 原始响应 | 需要时可获取更多细节 |
cause | unknown | 原始错误对象(v1.2.10+) | 追溯错误源头 |
AI 友好的 description 字段
description 是 SDK 专为 AI 设计的核心字段(v1.2.5+),它包含:
- 错误原因 - 服务端返回了什么错误
- 错误分类 - 这是什么类型的错误
- 状态码 - HTTP 状态码是多少
- 修复建议 - 针对性的修复方向
description 的结构
服务端返回错误: {错误消息}。错误类型: {类型}。状态码: {status}。建议: {具体建议}
这种结构化的自然语言格式,让 AI 能够:
- 解析出关键信息(字段名、错误类型)
- 理解问题的严重程度
- 按照建议采取行动
Vibe Coding 实战场景
以下展示 AI 如何利用 description 自动修复错误。
场景一:字段名拼写错误
你在 Cursor 中写代码:
await client.models.users.create({
naem: "张三", // 拼写错误
phone: "13800138000"
});
运行后 SDK 抛出错误:
LovrabetError {
message: "naem列不存在",
code: "SERVER_ERROR",
status: 400,
description: "服务端返回错误: naem列不存在。错误类型: 参数错误。状态码: 400。建议: 字段 \"naem\" 不存在,请检查字段名是否拼写正确; 使用 MCP 工具获取数据集的正确字段列表"
}
AI 的理解过程:
- 解析
description,发现是"参数错误" - 识别出问题字段是
naem - 看到建议"检查字段名是否拼写正确"
- 推断
naem可能是name的拼写错误 - 自动修复代码
// AI 自动修复后
await client.models.users.create({
name: "张三", // 已修复
phone: "13800138000"
});
场景二:缺少必填字段
await client.models.orders.create({
name: "订单1",
amount: 100
});
SDK 错误信息:
LovrabetError {
message: "project_id列不能为空",
code: "SERVER_ERROR",
status: 400,
description: "服务端返回错误: project_id列不能为空。错误类型: 参数错误。状态码: 400。建议: 字段 \"project_id\" 是必填项,请确保传递该字段"
}
AI 的处理方式:
- 识别出
project_id是必填项 - 检查当前代码,确认该字段确实缺失
- 可能通过 MCP 工具查询数据集结构,了解
project_id的类型 - 提示用户补充该字段,或根据上下文自动补充
场景三:权限/登录问题
await client.models.users.filter();
SDK 错误信息:
LovrabetError {
message: "权限不足",
code: "SERVER_ERROR",
status: 401,
description: "服务端返回错误: 权限不足。错误类型: 202。状态码: 401。建议: 检查用户登录态是否过期,需要重新登录; 检查 appCode 是否有访问该数据集的权限; 确保使用 HTTPS 协议访问; 检查是否存在跨域问题(CORS)"
}
AI 的排查方向:
- 看到 401 状态码,识别为认证问题
- 根据建议,依次排查:
- 登录态是否过期
- appCode 权限配置
- HTTPS 协议
- CORS 配置
- 给用户提供具体的排查步骤
与 MCP 工具协同
description 中会引导 AI 使用 MCP 工具获取更多信息:
建议: 字段 "xxx" 不存在,请检查字段名是否拼写正确; 使用 MCP 工具获取数据集的正确字段列表
当 AI 看到这个建议时,会调用 MCP 工具:
// AI 调用 MCP 工具
const datasetInfo = await mcp.tools.get_dataset_detail({
datasetCode: "users"
});
// 获取正确的字段列表
const fields = datasetInfo.fields;
// ["id", "name", "phone", "email", "created_at", ...]
然后 AI 就能:
- 找到正确的字段名
- 了解哪些字段是必填的
- 知道字段的类型和格式要求
这种 SDK + MCP 的协同架构,让 AI 能够完整地理解和解决问题。
错误码参考
客户端错误码
| 错误码 | 说明 | description 内容 |
|---|---|---|
MODEL_NOT_FOUND | 模型不存在 | 列出所有可用模型(datasetCode、alias、name) |
MODEL_INDEX_OUT_OF_RANGE | 模型索引越界 | 提供有效索引范围 |
CONFIG_NOT_FOUND | 配置不存在 | 列出已注册的配置名称 |
APP_CODE_REQUIRED | 缺少 appCode | 提供配置示例 |
TIMEOUT | 请求超时 | 当前超时时间、优化建议 |
OPENAPI_AUTH_PARAMS_MISSING | OpenAPI 认证参数缺失 | 列出缺失的参数 |
服务端错误码
| 错误类型 | HTTP 状态码 | description 内容 |
|---|---|---|
| 参数错误 | 400 | 字段修复建议(必填、拼写、格式) |
| 权限不足 | 401 | 登录态、appCode、HTTPS、CORS 检查建议 |
| 其他错误 | 各种 | 基本信息(错误类型、消息、状态码) |
safe 函数:无 try-catch 错误处理 v1.2.10+
除了传统的 try-catch 模式,SDK 还提供了 safe 函数,让你无需 try-catch 即可优雅地处理错误。
基本用法
import { safe } from "@lovrabet/sdk";
// 新风格:无 try-catch
const { data, error } = await safe(() =>
client.models.users.filter({ where: { status: 'active' } })
);
if (error) {
console.error("查询失败:", error.message, error.description);
return;
}
// 使用 data
console.log("用户列表:", data);
与 try-catch 对比
| 方面 | try-catch 模式 | safe 模式 |
|---|---|---|
| 代码量 | 较多(try-catch 嵌套) | 较少(解构赋值) |
| 嵌套层级 | 容易产生嵌套地狱 | 扁平化 |
| 错误类型 | 需要手动判断 | 总是 LovrabetError |
| 早期返回 | 需要 throw 或 return | 直接 return |
| 适用场景 | 复杂错误处理逻辑 | 简单的条件判断 |
使用场景对比
try-catch 适合复杂场景:
try {
const user = await client.models.users.getOne(userId);
const orders = await client.models.orders.filter({ userId });
const stats = await client.api.executeSql('user-stats', { userId });
return { user, orders, stats };
} catch (error) {
if (error instanceof LovrabetError) {
if (error.status === 404) {
throw new Error("用户不存在");
} else if (error.status === 403) {
throw new Error("无权访问");
}
}
throw error;
}
safe 适合简单场景:
// 场景 1:单个 API 调用
const { data, error } = await safe(() => client.models.users.getOne(userId));
if (error) return { success: false, error: error.message };
return { success: true, data };
// 场景 2:顺序操作
const result1 = await safe(() => client.models.users.getOne(userId));
if (result1.error) return { error: result1.error.message };
const result2 = await safe(() => client.models.orders.filter({ userId }));
if (result2.error) return { error: result2.error.message };
return { user: result1.data, orders: result2.data };
类型定义
interface SafeResult<T> {
data: T | null; // 成功时的数据
error: LovrabetError | null; // 失败时的错误
}
function safe<T>(
fn: Promise<T> | (() => Promise<T>)
): Promise<SafeResult<T>>;
高级用法
处理并发请求:
const [usersResult, ordersResult, statsResult] = await Promise.all([
safe(() => client.models.users.filter()),
safe(() => client.models.orders.filter()),
safe(() => client.api.executeSql('daily-stats')),
]);
// 检查各自的结果
if (usersResult.error) {
console.error("获取用户失败:", usersResult.error.message);
}
if (ordersResult.error) {
console.error("获取订单失败:", ordersResult.error.message);
}
if (statsResult.error) {
console.error("获取统计失败:", statsResult.error.message);
}
// 使用成功的返回值
console.log("用户:", usersResult.data);
console.log("订单:", ordersResult.data);
console.log("统计:", statsResult.data);
封装错误处理工具:
import { safe, LovrabetError } from "@lovrabet/sdk";
// 统一的 API 调用处理
async function handleApiCall<T>(
operation: () => Promise<T>,
errorMessage: string
): Promise<T> {
const { data, error } = await safe(operation);
if (error) {
// 记录错误
console.error(`${errorMessage}:`, error.message, error.description);
// 可以在这里添加日志上报
throw new Error(errorMessage);
}
return data!;
}
// 使用
const users = await handleApiCall(
() => client.models.users.filter({ status: 'active' }),
"获取活跃用户失败"
);
向后兼容
safe 函数不影响现有代码,两种模式可以共存:
// 旧代码继续工作
try {
const data = await client.models.users.filter();
console.log(data);
} catch (e) {
console.error(e);
}
// 新代码也可以用 safe
const { data, error } = await safe(() => client.models.users.filter());
if (error) {
console.error(error);
} else {
console.log(data);
}
最佳实践
让 AI 能看到错误信息
在 Vibe Coding 时,确保错误信息能被 AI 工具捕获:
try {
await client.models.users.create(formData);
} catch (error) {
if (error instanceof LovrabetError) {
// 输出 description,AI 工具会读取控制台
console.error("SDK Error:", error.description);
// 或者直接抛出,让 AI 看到完整堆栈
throw error;
}
}
全局错误处理
配置全局错误处理,统一输出 AI 友好的信息:
const client = createClient({
appCode: "your-app-code",
options: {
onError: (error: LovrabetError) => {
// 输出 AI 友好的描述
console.error("[Lovrabet SDK Error]", error.description);
// 401 自动跳转登录
if (error.status === 401) {
window.location.href = "/login";
}
},
},
models: [
{ tableName: "users", datasetCode: "xxx", alias: "users" },
],
});
开发环境增强输出
开发环境下输出更多信息:
function handleError(error: LovrabetError) {
if (process.env.NODE_ENV === "development") {
console.group("LovrabetError Debug Info");
console.log("Message:", error.message);
console.log("Code:", error.code);
console.log("Status:", error.status);
console.log("Description:", error.description);
console.log("Response:", JSON.stringify(error.response, null, 2));
console.groupEnd();
}
}
错误类型判断
按 HTTP 状态码
if (error instanceof LovrabetError) {
switch (error.status) {
case 400:
// 参数错误 - AI 可以根据 description 自动修复
break;
case 401:
// 认证失败 - 需要重新登录
break;
case 403:
// 权限不足 - 检查 appCode 配置
break;
case 500:
// 服务器错误 - 需要联系运维
break;
}
}
按错误码
if (error instanceof LovrabetError) {
switch (error.code) {
case "MODEL_NOT_FOUND":
// 查看 description 获取可用模型列表
console.log(error.description);
break;
case "SERVER_ERROR":
// 查看 description 获取具体原因和建议
console.log(error.description);
break;
}
}
总结
Lovrabet SDK 的 AI 友好错误处理架构:
| 特性 | 说明 |
|---|---|
| 统一错误类型 | 所有错误都是 LovrabetError,便于统一处理 |
| AI 可理解的 description | 包含错误原因、类型、建议,AI 可直接解析 |
| 针对性修复建议 | 不同错误类型提供不同的修复方向 |
| MCP 工具协同 | 引导 AI 使用 MCP 获取更多信息 |
| 支持自动修复 | AI 可以根据信息自动修改代码 |
在 Vibe Coding 时代,好的错误信息不仅要让人能看懂,更要让 AI 能理解并帮你解决问题。
更多高级错误处理模式(重试机制、断路器等),请参考 高级功能。