accounts/docs/api/errors.md
2026-04-14 16:32:15 +08:00

20 KiB
Raw Permalink Blame History

Error Conventions / 错误约定

中文

通用原则

当前 API 没有单独的全局 error schema package而是由几类 handler 约定共同形成:

  1. 大多数业务 handler 使用 respondError,返回统一 envelope。
  2. 一部分 internal / agent / GORM 简单 handler 直接 c.JSON,只返回 errorerror + message
  3. 因此文档层面必须区分“稳定错误结构”和“简化错误结构”,不能假设所有接口完全一致。

标准错误 envelope

大多数认证、账户、管理员、XWorkmate、计费接口的失败响应是

{"error":"code","message":"human readable message"}

字段含义:

字段 含义
error 机器可读错误码,通常稳定,适合前端做分支。
message 面向人类的错误描述。

扩展错误 envelope

少数接口会在标准形状上附加字段,例如:

场景 额外字段
MFA 锁定 retryAtmfaToken
Admin settings 乐观并发冲突 versionmatrix
Sandbox binding / GORM 错误 有时直接返回底层 err.Error() 作为 message
/api/ping 不走错误 envelope是纯成功读取接口

简化错误 envelope

以下 handler 家族经常直接返回简化结构:

{"error":"some_code"}

{"error":"some_code","message":"..."}

典型来源:

文件 典型接口
api/agent_server.go /api/agent-server/v1/users/status
api/user_agents.go /api/agent-server/v1/nodes、legacy /api/agent/nodes
api/internal_sandbox_guest.go /api/internal/sandbox/guest
api/admin_sandbox.go /api/auth/admin/sandbox/*/api/admin/sandbox/*
internal/auth/middleware.go JWT / internal-service middleware 直接中断请求时

错误来源分层

来源层 典型错误码 / 文本 说明
请求绑定与参数校验 invalid_requestmissing_credentialsinvalid_emailpassword_too_short JSON body 缺字段、query 中带敏感参数、格式不对。
Session / JWT / internal token session_token_requiredinvalid_sessionmissing authorization headerinvalid or expired tokenmissing service token 认证前置失败。
角色 / 权限 / 账户状态 forbiddenroot_onlyaccount_suspendedread_only_accountroot_email_enforced 用户存在,但当前身份不允许执行操作。
业务状态 email_already_existssubscription_not_foundmfa_not_enabledpolicy_not_found 领域对象状态不满足当前请求。
外部系统或后台依赖 verification_failedxworkmate_secret_write_failedstripe_cancel_failedcollector_status_unavailable SMTP、Vault、Stripe、DB、Xray render 等依赖失败。

高频错误码索引

认证与会话

错误码 常见状态码 来源 含义
credentials_in_query 400 api/api.go 登录或敏感接口不允许把凭据放在 query 中。
missing_credentials 400 api/api.go 登录、注册缺少关键字段。
user_not_found 404 api/api.goapi/user_agents.go 通过 identifier 或 session userID 找不到用户。
invalid_credentials 401 api/api.go 密码校验失败。
email_not_verified 401 api/api.go 邮箱尚未验证,禁止登录或 OAuth 登录。
session_token_required 401 api/api.goapi/xworkmate.goapi/admin_users_metrics.go 需要 session token。
invalid_session 401 多个 session-based handler session 不存在、过期或无法匹配。
session_user_lookup_failed 500 多个 handler session 存在,但无法回查用户。

MFA

错误码 常见状态码 来源 含义
mfa_ticket_required 400 verifyMFALogin 登录挑战完成接口缺少 ticket。
mfa_code_required 400 verifyMFALoginverifyTOTP 缺少 TOTP 验证码。
invalid_mfa_ticket 401 verifyMFALogin 登录用 MFA challenge 已失效。
invalid_mfa_token 401 provisionTOTPverifyTOTP TOTP provisioning / verify 的 token 不存在或过期。
invalid_mfa_code 401 / 500 MFA handlers 验证码错误,或库校验过程失败。
mfa_challenge_locked 429 verifyTOTP 连续错误次数过多,被暂时锁定。
mfa_not_enabled 400 verifyMFALogindisableMFA 用户当前没有启用 MFA。

注册、邮箱验证、密码重置

错误码 常见状态码 来源 含义
verification_required 400 register 已启用邮箱验证,但未提供验证码。
invalid_code 400 registerverifyEmail 验证码错误或过期。
verification_failed 500 邮件验证流程 SMTP 发送或用户更新失败。
email_already_exists 409 registersendEmailVerification 邮箱已存在或已验证。
name_already_exists 409 register 用户名冲突。
password_reset_failed 500 password reset flows 密码重置邮件发送、用户更新或其他内部步骤失败。
invalid_token 400 confirmPasswordReset reset token 无效或过期。

OAuth / token exchange / refresh

错误码 常见状态码 来源 含义
provider_not_found 404 OAuth routes provider 未注册。
code_missing 400 oauthCallback callback query 中缺少 code
oauth_exchange_failed 500 oauthCallback 与 provider 交换 token 失败。
fetch_profile_failed 500 oauthCallback 拉取 provider profile 失败。
invalid_exchange_code 401 exchangeToken 一次性 exchange code 无效或已过期。
token_service_unavailable 503 refreshToken 当前未启用 token service。
invalid_refresh_token 401 refreshToken refresh token 无效或已过期。

管理员与权限

错误码 常见状态码 来源 含义
forbidden 403 requireAdminPermissionRequireRole 用户权限不足。
root_only 403 sandbox bind / assume / tenant bootstrap 只有 root 可执行。
root_email_enforced 403 requireAdminPermission root role 被限制给 admin@svc.plus
metrics_unavailable 503 / 其他 adminUsersMetrics 指标 provider 未配置或执行失败。
read_only_account 403 多个写接口 demo/read-only 账号禁止写操作。
account_suspended 403 session user checks 账号被暂停。

XWorkmate / Vault

错误码 常见状态码 来源 含义
xworkmate_vault_unavailable 503 ensureXWorkmateVaultService 当前未注入 Vault backend。
tenant_membership_required 403 xworkmate.go 当前用户没有 tenant membership。
tenant_not_found 404 xworkmate.go host 解析出的 tenant 不存在。
xworkmate_profile_forbidden 403 updateXWorkmateProfile 无权修改 tenant integration profile。
token_persistence_forbidden 400 updateXWorkmateProfile 禁止把 raw token/password/api key 直接落库。
xworkmate_secret_unknown_target 400 secret PUT/DELETE :target 不在允许列表内。
xworkmate_secret_write_failed 500 secret PUT 写入 Vault/backend 失败。
xworkmate_secret_delete_failed 500 secret DELETE 删除 Vault/backend secret 失败。

计费、订阅、流量与调度

错误码 常见状态码 来源 含义
subscription_not_found 404 cancelSubscription 订阅不存在。
subscription_upsert_failed 500 upsertSubscription 订阅落库失败。
stripe_cancel_failed 502 cancelSubscription 调用 Stripe 取消失败。
usage_summary_unavailable 500 accountUsageSummary 读取使用量汇总失败。
invalid_start / invalid_end 400 accountUsageBuckets 时间范围参数不是 RFC3339。
policy_not_found 404 accountPolicyinternalAccountPolicy 账户策略快照不存在。
collector_status_unavailable 500 adminCollectorStatus collector 读面不可用。
scheduler_status_unavailable 500 adminSchedulerStatus 调度决策读面不可用。

Agent 与内部服务

错误码 / 文本 常见状态码 来源 含义
missing_token 401 api/agent_server.go agent token 缺失。
invalid_token 401 api/agent_server.go agent token 无效。
agent_registry_unavailable 503 api/agent_server.go 未注入 agentserver.Registry
list_users_failed 500 internalPublicOverviewlistAgentUsersinternalNetworkIdentities 枚举用户失败。
store_not_configured / store_unavailable 503 internal handlers store 未配置。
sandbox_missing 404 sandbox guest handlers sandbox 用户不存在。

调用方建议

  1. respondError 路由,优先按 error 做程序分支,message 仅用于展示。
  2. 对 agent/internal 路由,不要假设一定有 message
  3. 429 mfa_challenge_locked,调用方应读取 retryAt 决定 UI 倒计时。
  4. POST /api/auth/admin/settings409,应读取返回的 versionmatrix 重新加载服务端最新值。

English

Core Rule

The current API does not have a single shared error-schema package. Instead, error behavior is shaped by a few implementation conventions:

  1. Most business handlers use respondError, which produces the standard envelope.
  2. Some internal / agent / simple GORM-backed handlers call c.JSON directly and return only error or error + message.
  3. Documentation therefore has to distinguish between the stable error envelope and simplified handler-local errors.

Standard Error Envelope

Most authentication, account, admin, XWorkmate, and accounting handlers return:

{"error":"code","message":"human readable message"}

Field meaning:

Field Meaning
error Machine-readable error code that is usually stable enough for frontend branching.
message Human-readable explanation.

Extended Error Envelope

Some handlers add extra fields on top of the standard shape:

Scenario Extra fields
MFA lockout retryAt, mfaToken
Admin settings optimistic conflict version, matrix
Sandbox binding / GORM errors Sometimes the raw err.Error() is surfaced in message
/api/ping Not an error-envelope route; it is a pure success read

Simplified Error Envelope

The following handler families commonly return:

{"error":"some_code"}

or:

{"error":"some_code","message":"..."}

Typical sources:

File Example APIs
api/agent_server.go /api/agent-server/v1/users, /status
api/user_agents.go /api/agent-server/v1/nodes, legacy /api/agent/nodes
api/internal_sandbox_guest.go /api/internal/sandbox/guest
api/admin_sandbox.go /api/auth/admin/sandbox/*, /api/admin/sandbox/*
internal/auth/middleware.go Direct JWT / internal-service middleware rejection responses

Error Sources By Layer

Source layer Typical codes / texts Meaning
Request binding and validation invalid_request, missing_credentials, invalid_email, password_too_short Bad JSON bodies, forbidden query-string credentials, invalid formats.
Session / JWT / internal token session_token_required, invalid_session, missing authorization header, invalid or expired token, missing service token Authentication precondition failed.
Role / permission / account-state checks forbidden, root_only, account_suspended, read_only_account, root_email_enforced The user exists but is not allowed to perform the action.
Business-state failures email_already_exists, subscription_not_found, mfa_not_enabled, policy_not_found Domain state does not satisfy the requested transition.
External or backend dependency failures verification_failed, xworkmate_secret_write_failed, stripe_cancel_failed, collector_status_unavailable SMTP, Vault, Stripe, DB, Xray rendering, and similar dependency failures.

High-Frequency Error Index

Authentication And Sessions

Code Typical status Source Meaning
credentials_in_query 400 api/api.go Sensitive credentials were sent through the query string.
missing_credentials 400 api/api.go Required login or registration fields are missing.
user_not_found 404 api/api.go, api/user_agents.go No user matches the identifier or session-derived user ID.
invalid_credentials 401 api/api.go Password verification failed.
email_not_verified 401 api/api.go The email is not verified, so login is blocked.
session_token_required 401 api/api.go, api/xworkmate.go, api/admin_users_metrics.go A session token is required.
invalid_session 401 Multiple session-based handlers The session does not exist, is expired, or cannot be matched.
session_user_lookup_failed 500 Multiple handlers The session exists but the backing user cannot be loaded.

MFA

Code Typical status Source Meaning
mfa_ticket_required 400 verifyMFALogin The MFA completion endpoint is missing its ticket.
mfa_code_required 400 verifyMFALogin, verifyTOTP No TOTP code was supplied.
invalid_mfa_ticket 401 verifyMFALogin The login MFA challenge has expired or is invalid.
invalid_mfa_token 401 provisionTOTP, verifyTOTP The provisioning / verification token does not exist or has expired.
invalid_mfa_code 401 / 500 MFA handlers The code is wrong, or the verification library errored.
mfa_challenge_locked 429 verifyTOTP Too many invalid attempts caused a temporary lockout.
mfa_not_enabled 400 verifyMFALogin, disableMFA The user does not currently have MFA enabled.

Registration, Email Verification, And Password Reset

Code Typical status Source Meaning
verification_required 400 register Email verification is enabled but the code was not provided.
invalid_code 400 register, verifyEmail The verification code is wrong or expired.
verification_failed 500 Email-verification flows SMTP delivery or user-update work failed.
email_already_exists 409 register, sendEmailVerification The email already exists or is already verified.
name_already_exists 409 register Username conflict.
password_reset_failed 500 Password-reset flows Email delivery, user update, or other internal reset steps failed.
invalid_token 400 confirmPasswordReset The reset token is invalid or expired.

OAuth, Token Exchange, And Refresh

Code Typical status Source Meaning
provider_not_found 404 OAuth routes The provider is not registered.
code_missing 400 oauthCallback The callback query does not contain code.
oauth_exchange_failed 500 oauthCallback Exchanging the provider code failed.
fetch_profile_failed 500 oauthCallback Fetching the provider profile failed.
invalid_exchange_code 401 exchangeToken The one-time exchange code is invalid or expired.
token_service_unavailable 503 refreshToken The token service is not enabled.
invalid_refresh_token 401 refreshToken The refresh token is invalid or expired.

Admin And Permission Errors

Code Typical status Source Meaning
forbidden 403 requireAdminPermission, RequireRole The caller lacks the required permission.
root_only 403 Sandbox bind / assume / tenant bootstrap flows Only the root user may perform the action.
root_email_enforced 403 requireAdminPermission The root role is restricted to admin@svc.plus.
metrics_unavailable 503 and others adminUsersMetrics The metrics provider is missing or failed.
read_only_account 403 Multiple write handlers Demo/read-only accounts are blocked from writes.
account_suspended 403 Session user checks The account has been suspended.

XWorkmate And Vault

Code Typical status Source Meaning
xworkmate_vault_unavailable 503 ensureXWorkmateVaultService No Vault backend has been injected.
tenant_membership_required 403 xworkmate.go The caller has no tenant membership.
tenant_not_found 404 xworkmate.go The host-resolved tenant does not exist.
xworkmate_profile_forbidden 403 updateXWorkmateProfile The caller may not update the tenant integration profile.
token_persistence_forbidden 400 updateXWorkmateProfile Raw token/password/api-key values may not be persisted directly.
xworkmate_secret_unknown_target 400 Secret PUT/DELETE handlers The :target path value is outside the allowed set.
xworkmate_secret_write_failed 500 Secret PUT Persisting the Vault/backend secret failed.
xworkmate_secret_delete_failed 500 Secret DELETE Deleting the Vault/backend secret failed.

Billing, Subscription, Traffic, And Scheduler Reads

Code Typical status Source Meaning
subscription_not_found 404 cancelSubscription The subscription does not exist.
subscription_upsert_failed 500 upsertSubscription Persisting the subscription failed.
stripe_cancel_failed 502 cancelSubscription Stripe cancellation failed.
usage_summary_unavailable 500 accountUsageSummary Usage summary reads failed.
invalid_start / invalid_end 400 accountUsageBuckets The time-range query parameters are not valid RFC3339 timestamps.
policy_not_found 404 accountPolicy, internalAccountPolicy No account policy snapshot is available.
collector_status_unavailable 500 adminCollectorStatus Collector read models are unavailable.
scheduler_status_unavailable 500 adminSchedulerStatus Scheduler decision reads are unavailable.

Agent And Internal-Service Errors

Code / text Typical status Source Meaning
missing_token 401 api/agent_server.go The agent token is missing.
invalid_token 401 api/agent_server.go The agent token is invalid.
agent_registry_unavailable 503 api/agent_server.go No agentserver.Registry has been injected.
list_users_failed 500 internalPublicOverview, listAgentUsers, internalNetworkIdentities Enumerating users failed.
store_not_configured / store_unavailable 503 Internal handlers The store has not been configured.
sandbox_missing 404 Sandbox guest handlers The sandbox user does not exist.

Client Guidance

  1. For respondError-based routes, branch on error first and treat message as display text.
  2. For agent/internal routes, do not assume message is always present.
  3. For 429 mfa_challenge_locked, read retryAt and drive the UI countdown from it.
  4. For 409 from POST /api/auth/admin/settings, reload the server-returned version and matrix before retrying.