Repository navigation
Api Error Handling
worable edited this page Oct 12, 2026
·
1 revision
StackPanel API 统一使用 RFC 7807 / RFC 9457 problem details,Content-Type 为
application/problem+json。
所有错误响应都是 JSON problem details:
{
"type": "https://errors.stackpanel.dev/auth/forbidden",
"title": "Forbidden",
"status": 403,
"detail": "没有权限执行此操作",
"instance": "/admin/users",
"code": "auth.forbidden",
"requestId": "req-8",
"errors": [{ "field": "email", "code": "validation.invalid_format", "message": "Invalid email" }]
}| 字段 | 说明 |
|---|---|
type |
由 code 派生的 URI:https://errors.stackpanel.dev/ 加 code 中 . 替换为 /
|
title |
中性英文标题(按状态码) |
status |
HTTP 状态码,与响应一致 |
detail |
可读说明;5xx 不泄露内部信息 |
instance |
产生错误的请求路径 |
code |
稳定契约,命名空间化(如 auth.forbidden、sp_v1.nonce_replayed) |
requestId |
关联 ID,同时写入 API 日志 |
errors |
字段级校验失败,仅校验错误才出现 |
内核 onSend 会把遗留的 { "error": "..." } 响应体提升为 detail,但不再输出
error 成员。调用方应读取 code(机器判断)与 detail / title(展示)。
| 状态码 | 含义 | 触发场景 |
|---|---|---|
| 400 | 请求无效 | 路由内手工校验失败、参数格式错误 |
| 401 | 未认证 | 缺少或无效的会话/Token/签名 |
| 403 | 禁止访问 | 权限或 scope 不足 |
| 404 | 未找到 | 资源不存在、插件未激活、非回环访问 /metrics
|
| 405 | 方法不允许 |
/mcp 的 GET 等不支持的传输方法 |
| 409 | 冲突 | 资源已存在、依赖冲突、路由冲突 |
| 410 | 已移除 | 资源已下线 |
| 413 | 请求体过大 | 文件上传或签名体超过限制 |
| 415 | 媒体类型不支持 | 上传类型不受支持 |
| 422 | 实体不可处理 | schema 校验失败、ZIP/签名校验失败 |
| 429 | 请求过多 | 限流 / 配额 / 渠道 RPM |
| 500 | 服务器错误 | 未捕获的异常 |
| 501 | 未实现 | 功能未配置,如密钥存储未启用、缺少 pg 工具 |
| 503 | 服务不可用 | 依赖不可达、导入维护模式 |
未匹配路由由 setNotFoundHandler 返回 404 request.not_found。
内核 setErrorHandler(apps/api/src/app.ts)的处理顺序:
error →
if isPluginError(error): # 插件或内核显式抛出,品牌检查而非 instanceof
return buildProblem({ status, code, detail, errors }) + status
else if 是 schema 校验错误 (validation 数组):
return problem(code="validation.invalid", detail="请求参数无效") + 422
else if statusCode 是 4xx:
return problem(detail=error.message ?? "无效请求") + statusCode
else:
log error
return problem(code="internal.unexpected", detail="服务器内部错误") + 500
PluginError 属于预期结果,以 info 级别记录;其余错误按 error 级别入日志。5xx 的 详细信息只入日志,不返回给客户端。
// 401 auth.unauthenticated
{ "code": "auth.unauthenticated", "status": 401, "detail": "未登录或会话已过期" }
// 401 auth.invalid_credentials
{ "code": "auth.invalid_credentials", "status": 401, "detail": "邮箱或密码错误" }// 403 auth.forbidden
{ "code": "auth.forbidden", "status": 403, "detail": "没有权限执行此操作" }权限不足时会同时写入审计日志,action 为 auth.forbidden。
// 429 request.rate_limited(每 Token RPM)
{ "code": "request.rate_limited", "status": 429, "detail": "请求过于频繁,请稍后再试" }
// 429 request.concurrent_request(每 Token 并发)
{ "code": "request.concurrent_request", "status": 429, "detail": "并发请求超出限制,请稍后再试" }
// 401 sp_v1.signature_invalid / sp_v1.nonce_replayed / sp_v1.signature_expired
{ "code": "sp_v1.signature_invalid", "status": 401, "detail": "请求签名无效" }
// 403 sp_v1.scope_forbidden
{ "code": "sp_v1.scope_forbidden", "status": 403, "detail": "缺少能力授权:order:write" }// 404 request.not_found(插件未激活或路由不存在)
{ "code": "request.not_found", "status": 404, "detail": "接口不存在" }
// 409 request.conflict(依赖冲突)
{ "code": "request.conflict", "status": 409, "detail": "插件 store 被已启用的插件依赖:my-plugin" }// 422 validation.invalid
{ "code": "validation.invalid", "status": 422, "detail": "插件包包含源码文件:src/index.ts" }
{ "code": "validation.invalid", "status": 422, "detail": "包签名无效" }
// 413 request.payload_too_large
{ "code": "request.payload_too_large", "status": 413, "detail": "文件过大或不是有效的 multipart 表单" }使用 @stackpanel/sdk 的 ApiClient 时,错误以 ApiError 抛出:
import { ApiClient, ApiError } from '@stackpanel/sdk';
try {
const result = await api.login(email, password);
} catch (err) {
if (err instanceof ApiError) {
console.log(err.status); // HTTP 状态码
console.log(err.code); // 稳定错误码(problem `code` / timeout / network / circuit_open)
console.log(err.message); // detail ?? title
console.log(err.details); // 原始响应体
console.log(err.requestId); // 关联 ID
console.log(err.errors); // 字段级校验错误
}
}| 属性 | 说明 |
|---|---|
status |
HTTP 状态码(网络错误为 0) |
code |
problem code;传输层错误为 timeout / network / circuit_open / unknown
|
message |
detail 优先,其次 title
|
details |
原始响应体 JSON(如有) |
requestId |
problem requestId(如有) |
errors |
problem errors[](如有) |
返回类型与完整属性定义见 SDK 客户端。
核心开发
插件开发
主题开发
前端包开发
RESTful API