API 错误码对照表
本文档详细说明了源丰后端API系统中所有错误码的含义、原因和解决方案。
📋 概述
API使用统一的错误响应格式,所有错误都会返回相应的状态码和错误信息。理解这些错误码有助于快速定位和解决问题。
🎯 通用响应格式
成功响应
json
{
"success": true,
"message": "操作成功",
"data": { /* 具体数据 */ }
}错误响应
简单错误响应
json
{
"success": false,
"message": "资源不存在"
}字段验证错误响应
json
{
"success": false,
"message": "参数验证失败",
"errors": [
{
"field": "用户名",
"tag": "min",
"value": "ab",
"message": "字段 '用户名' 长度不能小于 3 位",
"param": "3"
},
{
"field": "邮箱",
"tag": "email",
"value": "invalid-email",
"message": "字段 '邮箱' 邮箱格式不正确",
"param": ""
}
]
}🔢 HTTP 状态码
| 状态码 | 类别 | 说明 |
|---|---|---|
| 200 | 成功 | 请求处理成功 |
| 201 | 成功 | 资源创建成功 |
| 204 | 成功 | 请求成功,无返回内容 |
| 400 | 客户端错误 | 请求参数错误 |
| 401 | 客户端错误 | 未授权,需要登录 |
| 403 | 客户端错误 | 权限不足 |
| 404 | 客户端错误 | 资源不存在 |
| 409 | 客户端错误 | 资源冲突 |
| 422 | 客户端错误 | 参数验证失败 |
| 429 | 客户端错误 | 请求频率超限 |
| 500 | 服务器错误 | 服务器内部错误 |
| 502 | 服务器错误 | 网关错误 |
| 503 | 服务器错误 | 服务不可用 |
📊 业务错误码详解
认证授权相关 (AUTH_***)
| 错误码 | 状态码 | 说明 | 常见原因 | 解决方案 |
|---|---|---|---|---|
AUTH_INVALID_CREDENTIALS | 401 | 无效的登录凭据 | 用户名或密码错误 | 检查用户名和密码,重新输入 |
AUTH_TOKEN_EXPIRED | 401 | 访问令牌已过期 | Token超过有效期 | 重新登录获取新token |
AUTH_TOKEN_INVALID | 401 | 无效的访问令牌 | Token格式错误或被篡改 | 重新登录获取新token |
AUTH_TOKEN_MISSING | 401 | 缺少访问令牌 | 请求头未携带Authorization | 添加Bearer token到请求头 |
AUTH_USER_NOT_FOUND | 404 | 用户不存在 | 用户ID不存在 | 检查用户ID或联系管理员 |
AUTH_USER_DISABLED | 403 | 用户账户已禁用 | 用户被管理员禁用 | 联系管理员启用账户 |
AUTH_ACCOUNT_LOCKED | 423 | 账户已锁定 | 多次登录失败被锁定 | 等待解锁时间或联系管理员 |
AUTH_PERMISSION_DENIED | 403 | 权限不足 | 用户无访问权限 | 联系管理员分配相应权限 |
用户管理相关 (USER_***)
| 错误码 | 状态码 | 说明 | 常见原因 | 解决方案 |
|---|---|---|---|---|
USER_ALREADY_EXISTS | 409 | 用户已存在 | 邮箱或手机号已被注册 | 使用其他邮箱或手机号 |
USER_EMAIL_INVALID | 400 | 邮箱格式无效 | 邮箱格式不正确 | 检查邮箱格式 |
USER_PHONE_INVALID | 400 | 手机号格式无效 | 手机号格式不正确 | 检查手机号格式 |
USER_PASSWORD_WEAK | 400 | 密码强度不足 | 密码过于简单 | 使用更复杂的密码 |
USER_PASSWORD_INCORRECT | 400 | 原密码错误 | 修改密码时原密码不正确 | 确认原密码是否正确 |
USER_PROFILE_INCOMPLETE | 400 | 用户资料不完整 | 必填字段缺失 | 补充完整的用户资料 |
USER_AVATAR_TOO_LARGE | 400 | 头像文件过大 | 头像超过大小限制 | 压缩图片或选择更小的文件 |
员工管理相关 (EMPLOYEE_***)
| 错误码 | 状态码 | 说明 | 常见原因 | 解决方案 |
|---|---|---|---|---|
EMPLOYEE_ALREADY_EXISTS | 409 | 员工已存在 | 员工工号或身份证重复 | 检查工号和身份证号 |
EMPLOYEE_NOT_FOUND | 404 | 员工不存在 | 员工ID不存在 | 检查员工ID |
EMPLOYEE_DEPARTMENT_INVALID | 400 | 部门无效 | 部门ID不存在 | 选择有效的部门 |
EMPLOYEE_POSITION_INVALID | 400 | 职位无效 | 职位设置不正确 | 检查职位配置 |
EMPLOYEE_STATUS_INVALID | 400 | 员工状态无效 | 状态值不在允许范围内 | 使用正确的状态值 |
EMPLOYEE_DELETE_ACTIVE | 409 | 无法删除在职员工 | 员工处于在职状态 | 先修改员工状态为离职 |
公司管理相关 (COMPANY_***)
| 错误码 | 状态码 | 说明 | 常见原因 | 解决方案 |
|---|---|---|---|---|
COMPANY_ALREADY_EXISTS | 409 | 公司已存在 | 公司名称或统一信用代码重复 | 检查公司信息 |
COMPANY_NOT_FOUND | 404 | 公司不存在 | 公司ID不存在 | 检查公司ID |
COMPANY_NAME_INVALID | 400 | 公司名称无效 | 公司名称格式不正确 | 使用规范的公司名称 |
COMPANY_CODE_INVALID | 400 | 统一信用代码无效 | 代码格式不正确 | 检查统一信用代码格式 |
COMPANY_STATUS_INVALID | 400 | 公司状态无效 | 状态值不在允许范围内 | 使用正确的状态值 |
COMPANY_QUOTA_EXCEEDED | 429 | 公司配额超限 | 员工数量超过限制 | 联系管理员增加配额 |
考勤管理相关 (ATTENDANCE_***)
| 错误码 | 状态码 | 说明 | 常见原因 | 解决方案 |
|---|---|---|---|---|
ATTENDANCE_ALREADY_CLOCKED_IN | 409 | 今日已上班打卡 | 重复上班打卡 | 检查打卡记录 |
ATTENDANCE_ALREADY_CLOCKED_OUT | 409 | 今日已下班打卡 | 重复下班打卡 | 检查打卡记录 |
ATTENDANCE_NOT_CLOCKED_IN | 400 | 今日未上班打卡 | 下班打卡前未上班打卡 | 先进行上班打卡 |
ATTENDANCE_LOCATION_INVALID | 400 | 打卡位置无效 | 不在允许的打卡范围内 | 移动到允许范围内打卡 |
ATTENDANCE_TIME_INVALID | 400 | 打卡时间无效 | 不在允许的打卡时间范围内 | 在允许时间内打卡 |
ATTENDANCE_RULE_NOT_FOUND | 404 | 考勤规则不存在 | 规则ID不存在 | 检查规则ID |
ATTENDANCE_GROUP_NOT_FOUND | 404 | 考勤组不存在 | 考勤组ID不存在 | 检查考勤组ID |
薪资管理相关 (SALARY_***)
| 错误码 | 状态码 | 说明 | 常见原因 | 解决方案 |
|---|---|---|---|---|
SALARY_ALREADY_EXISTS | 409 | 薪资记录已存在 | 该月薪资已生成 | 检查薪资记录 |
SALARY_NOT_FOUND | 404 | 薪资记录不存在 | 薪资ID不存在 | 检查薪资ID |
SALARY_PERIOD_INVALID | 400 | 薪资期间无效 | 月份格式不正确 | 使用正确的年月格式 |
SALARY_AMOUNT_INVALID | 400 | 薪资金额无效 | 金额为负数或超出范围 | 检查金额输入 |
SALARY_CATEGORY_NOT_FOUND | 404 | 薪资分类不存在 | 分类ID不存在 | 检查分类ID |
SALARY_STATUS_INVALID | 400 | 薪资状态无效 | 状态值不在允许范围内 | 使用正确的状态值 |
SALARY_CALCULATION_ERROR | 500 | 薪资计算错误 | 计算逻辑异常 | 联系技术支持 |
待办事项相关 (TODO_***)
| 错误码 | 状态码 | 说明 | 常见原因 | 解决方案 |
|---|---|---|---|---|
TODO_NOT_FOUND | 404 | 待办事项不存在 | 待办事项ID不存在 | 检查待办事项ID |
TODO_ACCESS_DENIED | 403 | 无访问权限 | 不是创建者或被指派人 | 检查权限设置 |
TODO_STATUS_INVALID | 400 | 状态无效 | 状态值不在允许范围内 | 使用正确的状态值 |
TODO_PRIORITY_INVALID | 400 | 优先级无效 | 优先级值不在允许范围内 | 使用正确的优先级 |
TODO_DUE_DATE_PAST | 400 | 截止日期已过期 | 截止日期早于当前日期 | 使用未来的日期 |
TODO_ASSIGNMENT_INVALID | 400 | 指派无效 | 指派给不存在的人 | 检查指派对象 |
文件管理相关 (FILE_***)
| 错误码 | 状态码 | 说明 | 常见原因 | 解决方案 |
|---|---|---|---|---|
FILE_NOT_FOUND | 404 | 文件不存在 | 文件ID或路径不存在 | 检查文件ID |
FILE_TOO_LARGE | 413 | 文件过大 | 文件超过大小限制 | 压缩文件或选择小文件 |
FILE_TYPE_INVALID | 400 | 文件类型无效 | 不支持的文件类型 | 使用支持的文件类型 |
FILE_UPLOAD_FAILED | 500 | 文件上传失败 | 网络错误或存储问题 | 检查网络连接,重试上传 |
FILE_DELETE_FAILED | 500 | 文件删除失败 | 权限不足或文件不存在 | 检查权限和文件存在性 |
FILE_QUOTA_EXCEEDED | 429 | 存储配额超限 | 超过存储空间限制 | 清理无用文件或增加配额 |
消息通知相关 (MESSAGE_***)
| 错误码 | 状态码 | 说明 | 常见原因 | 解决方案 |
|---|---|---|---|---|
MESSAGE_NOT_FOUND | 404 | 消息不存在 | 消息ID不存在 | 检查消息ID |
MESSAGE_ACCESS_DENIED | 403 | 无访问权限 | 不是消息接收者 | 检查权限设置 |
MESSAGE_ALREADY_READ | 409 | 消息已读 | 重复标记已读 | 检查消息状态 |
MESSAGE_RECIPIENT_INVALID | 400 | 接收者无效 | 接收者ID不存在 | 检查接收者ID |
MESSAGE_CONTENT_TOO_LONG | 400 | 内容过长 | 消息内容超过限制 | 缩短消息内容 |
系统相关 (SYSTEM_***)
| 错误码 | 状态码 | 说明 | 常见原因 | 解决方案 |
|---|---|---|---|---|
SYSTEM_MAINTENANCE | 503 | 系统维护中 | 系统正在进行维护 | 等待维护完成 |
SYSTEM_OVERLOAD | 503 | 系统过载 | 请求量超过系统负载 | 稍后重试 |
SYSTEM_DATABASE_ERROR | 500 | 数据库错误 | 数据库连接或查询异常 | 联系技术支持 |
SYSTEM_CACHE_ERROR | 500 | 缓存错误 | 缓存服务异常 | 联系技术支持 |
SYSTEM_EXTERNAL_SERVICE_ERROR | 502 | 外部服务错误 | 依赖的外部服务异常 | 稍后重试或联系技术支持 |
🔧 错误处理最佳实践
客户端错误处理
javascript
// JavaScript 错误处理示例
async function apiRequest(url, options = {}) {
try {
const response = await fetch(url, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
...options.headers
},
...options
});
const data = await response.json();
if (!response.ok) {
// 根据状态码处理不同错误
switch (response.status) {
case 401:
// 处理认证错误
handleAuthError(data);
break;
case 403:
// 处理权限错误
handlePermissionError(data);
break;
case 404:
// 处理资源不存在错误
handleNotFoundError(data);
break;
case 422:
// 处理参数验证错误
handleValidationError(data);
break;
default:
// 处理其他错误
handleGenericError(data);
}
return null;
}
return data;
} catch (error) {
// 处理网络错误
handleNetworkError(error);
return null;
}
}
function handleAuthError(errorData) {
// 清除本地token,跳转到登录页
localStorage.removeItem('token');
window.location.href = '/login';
}
function handleValidationError(errorData) {
// 显示具体的字段错误信息
if (errorData.errors) {
errorData.errors.forEach(error => {
showFieldError(error.field, error.message);
});
} else {
showErrorMessage(errorData.message);
}
}Python 错误处理示例
python
import requests
from typing import Optional, Dict, Any
class APIClient:
def __init__(self, base_url: str):
self.base_url = base_url
self.token = None
def request(self, method: str, endpoint: str, data: Optional[Dict] = None) -> Dict[str, Any]:
url = f"{self.base_url}{endpoint}"
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {self.token}'
}
try:
response = requests.request(method, url, headers=headers, json=data)
response_data = response.json()
if response.ok:
return response_data
else:
self.handle_error(response.status_code, response_data)
return {}
except requests.exceptions.RequestException as e:
self.handle_network_error(e)
return {}
def handle_error(self, status_code: int, error_data: Dict[str, Any]):
if status_code == 401:
print("认证失败,请重新登录")
self.token = None
elif status_code == 403:
print("权限不足")
elif status_code == 404:
print("资源不存在")
elif status_code == 422:
print(f"参数验证失败: {error_data.get('message', '')}")
else:
print(f"请求失败: {error_data.get('message', '未知错误')}")
def handle_network_error(self, error: requests.exceptions.RequestException):
print(f"网络错误: {str(error)}")📱 错误信息显示建议
前端错误提示
- 用户友好的错误信息: 将技术错误码转换为用户能理解的语言
- 具体的操作指导: 告诉用户如何解决问题
- 错误分类显示: 根据错误严重程度使用不同的提示样式
- 错误日志记录: 记录详细错误信息便于调试
移动端适配
- 使用Toast或弹窗显示错误信息
- 考虑屏幕空间限制,提供简洁的错误描述
- 提供"重试"按钮方便用户操作
🔄 重试机制
自动重试策略
javascript
// 自动重试函数
async function retryRequest(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
if (response.ok) {
return await response.json();
}
// 如果是客户端错误,不重试
if (response.status >= 400 && response.status < 500) {
throw new Error(`Client error: ${response.status}`);
}
// 如果是服务器错误,等待后重试
if (response.status >= 500) {
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
continue;
}
} catch (error) {
if (i === maxRetries - 1) {
throw error;
}
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}📞 获取帮助
如果您遇到无法解决的错误:
- 查看文档: 参考相关API文档和错误码说明
- 检查日志: 查看浏览器控制台或服务器日志
- 联系支持: 提供错误码、请求信息和复现步骤
- 社区求助: 在开发者社区寻求帮助
最后更新: 2024-01-24 文档版本: v1.0 维护团队: 源丰后端开发团队