Blue GraphQL API 中所有错误代码的全面参考,按类别组织
错误响应格式
Blue 的 GraphQL API 按照 GraphQL 规范以标准化格式返回错误。当发生错误时,响应包含一个 errors
数组,详细信息说明了出错的原因。
示例错误响应
{
"errors": [
{
"message": "Todo was not found.",
"extensions": {
"code": "TODO_NOT_FOUND"
}
}
]
}
错误结构
每个错误对象包含:
- message: 人类可读的错误描述
- extensions.code: 机器可读的错误代码,用于程序处理
生产错误安全性
Blue 实施了一种错误暴露的安全系统:
- 安全错误: 向客户端显示实际的错误代码和消息
- 非安全错误: 返回通用的
INTERNAL_SERVER_ERROR
以隐藏敏感细节
- 资源未找到: 所有
*_NOT_FOUND
错误被视为安全并始终暴露
错误类别
Blue 定义了 108 个自定义错误代码,按以下类别组织:
身份验证和授权错误
错误代码 |
消息 |
描述 |
UNAUTHENTICATED |
"需要身份验证。" |
请求需要身份验证,但未提供 |
FORBIDDEN |
"您没有权限。" |
已验证但缺少所需权限 |
资源未找到错误(共 52 个)
核心资源
错误代码 |
消息 |
描述 |
TODO_NOT_FOUND |
"待办事项未找到。" |
记录/待办事项不存在或用户缺乏访问权限 |
TODO_LIST_NOT_FOUND |
"待办事项列表未找到。" |
列表不存在或用户缺乏访问权限 |
PROJECT_NOT_FOUND |
"项目未找到。" |
项目不存在或用户缺乏访问权限 |
COMPANY_NOT_FOUND |
"公司未找到。" |
公司不存在或用户缺乏访问权限 |
USER_NOT_FOUND |
"用户未找到。" |
用户在系统中不存在 |
自定义字段和表单
错误代码 |
消息 |
描述 |
CUSTOM_FIELD_NOT_FOUND |
"自定义字段未找到。" |
自定义字段不存在 |
CUSTOM_FIELD_OPTION_NOT_FOUND |
"自定义字段选项未找到。" |
选择字段选项不存在 |
FORM_NOT_FOUND |
"表单未找到。" |
表单模板不存在 |
FORM_FIELD_NOT_FOUND |
"表单字段未找到。" |
表单字段不存在 |
项目组件
错误代码 |
消息 |
描述 |
TAG_NOT_FOUND |
"标签未找到。" |
项目中不存在标签 |
AUTOMATION_NOT_FOUND |
"自动化未找到。" |
自动化规则不存在 |
CHART_NOT_FOUND |
"图表未找到。" |
仪表板图表不存在 |
WEBHOOK_NOT_FOUND |
"Webhook 未找到。" |
Webhook 配置不存在 |
TEMPLATE_NOT_FOUND |
"模板未找到。" |
项目模板不存在 |
评论和活动
错误代码 |
消息 |
描述 |
COMMENT_NOT_FOUND |
"评论未找到。" |
评论不存在 |
ACTIVITY_NOT_FOUND |
"活动未找到。" |
活动日志条目不存在 |
REACTION_NOT_FOUND |
"反应未找到。" |
评论反应不存在 |
其他资源
错误代码 |
消息 |
描述 |
FILE_NOT_FOUND |
"文件未找到。" |
文件附件不存在 |
SUBSCRIPTION_NOT_FOUND |
"订阅未找到。" |
计费订阅不存在 |
INVOICE_NOT_FOUND |
"发票未找到。" |
发票记录不存在 |
CHECKLIST_NOT_FOUND |
"检查清单未找到。" |
检查清单不存在 |
CHECKLIST_ITEM_NOT_FOUND |
"检查清单项未找到。" |
检查清单项不存在 |
PROJECT_ROLE_NOT_FOUND |
"项目角色未找到。" |
自定义项目角色不存在 |
PROJECT_ACCESS_NOT_FOUND |
"项目访问未找到。" |
用户项目访问不存在 |
NOTIFICATION_NOT_FOUND |
"通知未找到。" |
通知不存在 |
DASHBOARD_NOT_FOUND |
"仪表板未找到。" |
仪表板不存在 |
KEY_NOT_FOUND |
"密钥未找到。" |
设置密钥不存在 |
验证错误
错误代码 |
消息 |
描述 |
BAD_USER_INPUT |
"无效输入。" |
通用输入验证失败 |
VALIDATION_ERROR |
"无效参数" |
请求参数验证失败 |
BAD_EMAIL |
"您需要输入有效的电子邮件。" |
无效的电子邮件格式 |
INVALID_IDS |
"无效的 ID。" |
请求中的一个或多个 ID 无效 |
PHONE_INVALID |
"电话无效。" |
无效的电话号码格式 |
URL_INVALID |
"URL 无效。" |
无效的 URL 格式 |
INVALID_RECURRING_DUE_DATE |
"无效的重复任务截止日期" |
重复任务日期验证失败 |
INVALID_COLOR |
"无效的颜色" |
颜色值不符合预期格式 |
业务逻辑错误
限制和配额
错误代码 |
消息 |
描述 |
COMPANY_LIMIT |
"您已达到您账户的公司限制。" |
达到最大公司数 |
PROJECT_LIMIT |
"您已达到您公司的项目限制。" |
达到最大项目数 |
USER_LIMIT |
"您已达到您公司的用户限制。" |
达到最大用户数 |
PROJECT_TEMPLATE_LIMIT |
"您已达到您公司的模板限制。" |
达到最大模板数 |
CUSTOM_FIELD_LIMIT |
"自定义字段限制已达到。" |
达到最大自定义字段数 |
TODO_LIST_LIMIT |
"您已达到您项目的列表限制。" |
每个项目的最大列表数 |
TOO_MANY_TODOS |
"待办事项过多。" |
记录限制超出 |
TOO_MANY_OPTIONS |
"选项过多。" |
选择字段选项限制超出 |
MAX_FILE_SIZE |
"最大文件大小为 4.8GB" |
文件上传大小限制超出 |
资源冲突
错误代码 |
消息 |
描述 |
TAG_ALREADY_EXISTS |
"标签已存在。" |
项目中存在同名标签 |
COMPANY_SLUG_ALREADY_EXISTS |
"公司已存在。" |
公司 slug/URL 已被占用 |
USER_ALREADY_EXISTS |
"用户已存在。" |
用户电子邮件已注册 |
ALREADY_INVITED |
"用户已被邀请。" |
用户已有待处理的邀请 |
USER_ALREADY_IN_PROJECT |
"用户已在此项目中。" |
用户已拥有项目访问权限 |
FILE_TYPE_NOT_ALLOWED |
"不允许的文件类型。" |
上传的文件类型受限 |
权限和访问错误
错误代码 |
消息 |
描述 |
UNABLE_TO_DELETE_ONLY_ADMIN |
"无法删除公司中的唯一管理员。" |
无法移除最后一个管理员 |
UNABLE_TO_UPDATE_OWNER |
"无法更新所有者。" |
无法修改所有者权限 |
TODO_LIST_IS_HIDDEN |
"待办事项列表被隐藏。" |
列表对用户角色隐藏 |
COMPANY_NOT_ACTIVE |
"公司未激活。" |
公司订阅未激活 |
PROJECT_NOT_ACTIVE |
"项目未激活。" |
项目已归档/未激活 |
数据完整性错误
错误代码 |
消息 |
描述 |
UNABLE_TO_DELETE_LIST_WITH_TODOS |
"无法删除包含待办事项的列表。" |
列表必须为空才能删除 |
UNABLE_TO_DELTE_FILE |
"无法删除文件。" |
文件删除失败(代码中的拼写错误) |
UNABLE_TO_MOVE_TODO |
"无法移动待办事项。" |
无法在列表之间移动记录 |
DEPENDENCY_HAS_DEPENDENCY |
"依赖项有依赖项" |
检测到循环依赖 |
TODO_DEPENDS_ON_ITSELF |
"待办事项依赖于自身" |
自我引用依赖 |
Stripe/支付错误
错误代码 |
消息 |
描述 |
STRIPE_CREATING_CUSTOMER |
"在 Stripe 中创建客户时出错。" |
Stripe 客户创建失败 |
STRIPE_ALREADY_SUBSCRIBED |
"已订阅。" |
存在活动订阅 |
STRIPE_MISSING_PAYMENT_METHOD |
"缺少支付方式。" |
没有支付方式记录 |
STRIPE_CREATING_SUBSCRIPTION |
"在 Stripe 中创建订阅时出错。" |
订阅创建失败 |
STRIPE_UPDATING_SUBSCRIPTION |
"在 Stripe 中更新订阅时出错。" |
订阅更新失败 |
STRIPE_CHECKOUT_SESSION |
"在 Stripe 中创建结账会话时出错。" |
结账会话创建失败 |
STRIPE_CUSTOMER_PORTAL |
"在 Stripe 中创建客户门户时出错。" |
门户会话创建失败 |
STRIPE_TAX_ID |
"无法保存税号" |
税号验证/保存失败 |
PAYMENT_REQUIRED |
"需要支付。" |
功能需要有效订阅 |
NO_PAYMENT_REQUIRED |
"无需支付。" |
操作不需要支付 |
身份验证和会话错误
错误代码 |
消息 |
描述 |
INVALID_CREDENTIALS |
"凭据无效。" |
用户名/密码不正确 |
EXPIRED_RESET_TOKEN |
"重置令牌已过期。" |
密码重置令牌已过期 |
OAUTH_FAILED |
"OAuth 过程失败。" |
OAuth 身份验证失败 |
SAML_NOT_ENABLED |
"SSO (SAML) 未启用。" |
SAML SSO 未配置 |
SSO_AUTO_PROVISION_DISABLED |
"自动配置已禁用。" |
无法自动创建 SSO 用户 |
速率限制
速率限制由 graphql-rate-limit
包处理,具有不同的配置:
限制类型 |
窗口 |
最大请求 |
应用到 |
Standard |
60s |
500 |
Most queries/mutations |
Sensitive |
300s |
10 |
Password reset, auth operations |
Expensive |
60s |
20 |
Complex queries, bulk operations |
Search |
60s |
60 |
Search operations |
File Upload |
60s |
100 |
File upload operations |
当速率受到限制时,您将收到一个标准的 GraphQL 错误,消息指示超出限制。
系统和内部错误
错误代码 |
消息 |
描述 |
INTERNAL_SERVER_ERROR |
"内部服务器错误。" |
生产环境中非安全错误的通用错误 |
UNKNOWN_ERROR |
"未知错误。" |
发生意外错误 |
RESOLVER_NOT_FOUND |
"解析器未找到" |
缺少 GraphQL 解析器 |
FIELD_NOT_IN_SCHEMA |
"字段不在模式中" |
请求的字段不存在 |
错误处理最佳实践
客户端处理
try {
const result = await client.mutate({
mutation: CREATE_TODO,
variables: { input }
});
} catch (error) {
if (error.graphQLErrors?.length > 0) {
const errorCode = error.graphQLErrors[0].extensions?.code;
switch (errorCode) {
case 'UNAUTHENTICATED':
// Redirect to login
break;
case 'TODO_NOT_FOUND':
// Show "Record not found" message
break;
case 'VALIDATION_ERROR':
// Display validation errors
break;
default:
// Show generic error message
}
}
}
常见错误场景
- 需要身份验证:
UNAUTHENTICATED
- 用户需要登录
- 权限被拒绝:
FORBIDDEN
- 用户缺少所需角色/权限
- 资源未找到:
*_NOT_FOUND
- 资源不存在或用户无法访问
- 验证失败:
VALIDATION_ERROR
, BAD_USER_INPUT
- 检查输入参数
- 速率限制: 检查速率限制头并实施退避
- 需要支付:
PAYMENT_REQUIRED
- 功能需要订阅
相关文档