Error handling
ℹ️ Version requirement The AI-friendly error handling architecture requires
@lovrabet/sdkv1.2.5 or later.
The Lovrabet SDK uses an AI-friendly error handling architecture designed for Vibe Coding (AI-assisted programming). When you use the SDK inside AI coding tools such as Cursor, Claude Code, or Copilot, the AI can read the error messages directly and suggest fixes automatically.
Design philosophy
Why AI-friendly errors?
Traditional error handling speaks only to human developers:
// 传统错误 - AI 难以理解上下文
Error: "project_id列不能为空"In a Vibe Coding context, the AI needs more context before it can fix the problem for you:
- What kind of error is this? Bad parameters? A permissions issue?
- Which field is at fault?
- How should it be fixed? Any suggestions?
- How do I look up the correct field information?
The Lovrabet SDK's AI-friendly architecture was designed to answer exactly these questions.
Architecture goals
- Errors AI can understand - structured messages carrying error type, cause, and status code
- Actionable fix suggestions - concrete remediation directions per error type
- Tool guidance - when more information is needed, steer the AI toward the right MCP tools
- Auto-fix support - the AI can apply the suggested fixes to your code
The LovrabetError type
Every SDK error is thrown as the unified LovrabetError type:
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+)
}
}Error properties
| Property | Type | Purpose | How the AI uses it |
|---|---|---|---|
message | string | Short error message | Gets a quick grasp of the problem |
code | string | Error code | Classifies the error |
status | number | HTTP status code | Tells client-side from server-side problems |
description | string | AI-friendly detailed description | Understands the cause and gets fix suggestions |
response | object | Raw response | Digs into details when needed |
cause | unknown | Original error object (v1.2.10+) | Traces the error to its source |
The AI-friendly description field
description is the core field the SDK designed specifically for AI (v1.2.5+). It contains:
- What went wrong - the error the server returned
- Error classification - what kind of error this is
- Status code - the HTTP status
- Fix suggestions - targeted remediation steps
Structure of description
服务端返回错误: {错误消息}。错误类型: {类型}。状态码: {status}。建议: {具体建议}This structured natural-language format lets the AI:
- extract the key facts (field names, error type)
- gauge how severe the problem is
- act on the suggestions
Vibe Coding in practice
The scenarios below show how the AI uses description to fix errors automatically.
Scenario 1: a misspelled field name
You write this in Cursor:
await client.models.users.create({
naem: "张三", // 拼写错误
phone: "13800138000"
});When it runs, the SDK throws:
LovrabetError {
message: "naem列不存在",
code: "SERVER_ERROR",
status: 400,
description: "服务端返回错误: naem列不存在。错误类型: 参数错误。状态码: 400。建议: 字段 \"naem\" 不存在,请检查字段名是否拼写正确; 使用 MCP 工具获取数据集的正确字段列表"
}How the AI reasons:
- Parses
descriptionand identifies a parameter error - Spots the problem field:
naem - Reads the suggestion to check the field spelling
- Infers that
naemis likely a typo forname - Fixes the code automatically
// AI 自动修复后
await client.models.users.create({
name: "张三", // 已修复
phone: "13800138000"
});Scenario 2: a missing required field
await client.models.orders.create({
name: "订单1",
amount: 100
});SDK error:
LovrabetError {
message: "project_id列不能为空",
code: "SERVER_ERROR",
status: 400,
description: "服务端返回错误: project_id列不能为空。错误类型: 参数错误。状态码: 400。建议: 字段 \"project_id\" 是必填项,请确保传递该字段"
}How the AI handles it:
- Recognizes that
project_idis required - Checks the code and confirms the field is indeed missing
- May query the dataset schema via an MCP tool to learn the type of
project_id - Asks you for the value, or fills it in from context
Scenario 3: permissions and login issues
await client.models.users.filter();SDK error:
LovrabetError {
message: "权限不足",
code: "SERVER_ERROR",
status: 401,
description: "服务端返回错误: 权限不足。错误类型: 202。状态码: 401。建议: 检查用户登录态是否过期,需要重新登录; 检查 appCode 是否有访问该数据集的权限; 确保使用 HTTPS 协议访问; 检查是否存在跨域问题(CORS)"
}Where the AI looks:
Sees the 401 status and recognizes an authentication problem
Follows the suggestions in order:
- Is the login state expired?
- appCode permission configuration
- HTTPS protocol
- CORS configuration
Gives you concrete troubleshooting steps
Working with MCP tools
description steers the AI toward MCP tools when more information would help:
建议: 字段 "xxx" 不存在,请检查字段名是否拼写正确; 使用 MCP 工具获取数据集的正确字段列表Seeing this suggestion, the AI calls an MCP tool:
// AI 调用 MCP 工具
const datasetInfo = await mcp.tools.get_dataset_detail({
datasetCode: "users"
});
// 获取正确的字段列表
const fields = datasetInfo.fields;
// ["id", "name", "phone", "email", "created_at", ...]The AI can then:
- find the correct field name
- see which fields are required
- learn each field's type and format requirements
This SDK + MCP collaboration lets the AI fully understand and resolve the problem.
Error code reference
Client-side error codes
| Code | Meaning | description contains |
|---|---|---|
MODEL_NOT_FOUND | Model not found | A list of all available models (datasetCode, alias, name) |
MODEL_INDEX_OUT_OF_RANGE | Model index out of range | The valid index range |
CONFIG_NOT_FOUND | Configuration not found | The registered configuration names |
APP_CODE_REQUIRED | appCode missing | A configuration example |
TIMEOUT | Request timed out | The current timeout and tuning suggestions |
OPENAPI_AUTH_PARAMS_MISSING | OpenAPI auth parameters missing | The missing parameters |
Server-side error codes
| Error type | HTTP status | description contains |
|---|---|---|
| Parameter error | 400 | Field fix suggestions (required, spelling, format) |
| Insufficient permissions | 401 | Checks for login state, appCode, HTTPS, and CORS |
| Other errors | varies | Basic info (error type, message, status code) |
The safe function: error handling without try-catch v1.2.10+
Besides the traditional try-catch pattern, the SDK provides a safe function that lets you handle errors gracefully without try-catch.
Basic usage
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);Compared with try-catch
| Aspect | try-catch | safe |
|---|---|---|
| Code volume | More (nested try-catch) | Less (destructuring assignment) |
| Nesting | Easily spirals into callback hell | Flat |
| Error type | Manual checks required | Always LovrabetError |
| Early return | Requires throw or return | Just return |
| Best for | Complex error handling logic | Simple conditional checks |
When to use which
try-catch for complex flows:
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 for simple flows:
// 场景 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 };Type definitions
interface SafeResult<T> {
data: T | null; // 成功时的数据
error: LovrabetError | null; // 失败时的错误
}
function safe<T>(
fn: Promise<T> | (() => Promise<T>)
): Promise<SafeResult<T>>;Advanced usage
Handling concurrent requests:
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);Wrapping error handling utilities:
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' }),
"获取活跃用户失败"
);Backward compatibility
safe does not affect existing code — both patterns can coexist:
// 旧代码继续工作
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);
}Best practices
Let the AI see the errors
When Vibe Coding, make sure error output is visible to the AI tool:
try {
await client.models.users.create(formData);
} catch (error) {
if (error instanceof LovrabetError) {
// 输出 description,AI 工具会读取控制台
console.error("SDK Error:", error.description);
// 或者直接抛出,让 AI 看到完整堆栈
throw error;
}
}Global error handling
Configure global handling that emits AI-friendly output uniformly:
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" },
],
});Richer output in development
Output more detail while developing:
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();
}
}Inspecting error types
By HTTP status code
if (error instanceof LovrabetError) {
switch (error.status) {
case 400:
// 参数错误 - AI 可以根据 description 自动修复
break;
case 401:
// 认证失败 - 需要重新登录
break;
case 403:
// 权限不足 - 检查 appCode 配置
break;
case 500:
// 服务器错误 - 需要联系运维
break;
}
}By error code
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;
}
}Summary
The Lovrabet SDK's AI-friendly error handling architecture:
| Feature | Description |
|---|---|
| Unified error type | Every error is a LovrabetError, easy to handle uniformly |
| AI-readable description | Contains cause, type, and suggestions the AI can parse directly |
| Targeted fix suggestions | Each error type gets its own remediation direction |
| MCP tool collaboration | Guides the AI to fetch more information via MCP |
| Auto-fix support | The AI can modify code based on the information |
In the Vibe Coding era, a good error message must be readable not just by humans, but by the AI that solves the problem for you.
For more advanced error handling patterns (retries, circuit breakers, and so on), see Advanced features.