跳转到内容

错误码

错误响应统一格式:

{
"error": {
"code": "VALIDATION_ERROR",
"message": "display_name must be 2-24 characters",
"i18n_key": "error.validation.display_name_length",
"params": { "min": 2, "max": 24 }
}
}

字段:

字段类型用途
codestring稳定机器枚举——代码分支判断的唯一字段
messagestringfallback 文案,仅显示用,不要 parse
i18n_keystring客户端 i18n 翻译键
paramsobjecti18n 模板参数(如 {min:2,max:24}

下面按”高频 Top 15 错误码”+“按 HTTP 状态分类的全表”两部分组织。Top 15 每个独立 anchor,含 触发场景 / 根因 / 处理代码示例


高频 Top 15 错误码深度解析

TOKEN_EXPIRED

维度内容
HTTP401
Layer认证
SDK 自动恢复✓(自动调 /auth/refresh

触发场景:Access Token 5 分钟过期。SDK / curl 调用任意需要 user JWT 的端点都会遇到。

根因:Access Token TTL = 300s(短期 token + Refresh Token 长期 cookie 模型)。

处理

try {
await callApi();
} catch (err) {
if (err.code === "TOKEN_EXPIRED") {
const { access_token } = await fetch("/auth/refresh", {
method: "POST",
credentials: "include", // refresh_token cookie 自动携带
}).then(r => r.json());
// 用新 token 重试
return callApiWith(access_token);
}
throw err;
}

SDK 已内置自动处理;只有你自己调 REST 时需要手写。详见 认证

AGENT_TOKEN_INVALID

维度内容
HTTP401
Layer认证
SDK 自动恢复✗(不可恢复,需手工干预)

触发场景:Agent Token 被撤销 / 已过期 / 拼错。

根因

  1. Token 旋转后旧 token 立即失效(紧急模式)或 7 天宽限后失效(常规模式)
  2. 用户在 Hashee app 主动撤销了该 Agent token
  3. 环境变量配错(如把 staging token 用到 prod URL)

处理

agent.addErrorHandler((err) => {
if (err.code === "AGENT_TOKEN_INVALID") {
// 不可恢复 — 退出进程让 systemd / k8s 拉起新进程读新 token
notifyOps("agent token invalid", { agent_id: AGENT_ID });
process.exit(1);
}
});

详见 Token 旋转

AGENT_KEYS_MISMATCH

维度内容
HTTP409
LayerE2EE
SDK 自动恢复✗(不可恢复,需 ops 介入)

触发场景:客户端本地持有的 X25519/Ed25519 私钥与后端注册的公钥不匹配。

根因

  1. SDK 在 onKeyGenerated 回调里生成了新私钥但未持久化 → 重启时 SDK 又 生成一对新私钥 → 与后端公钥不符
  2. 多个 Agent 进程共用同一 agent_id 但不同私钥(违反”3 个 replica 共享 同一组私钥”约定)
  3. 误删本地 keystore.json

处理

Terminal window
# 1. 删除本地 keystore,让 SDK 下次启动时重新生成 + 重新注册
rm -rf ~/.hashee/<agent_id>/keystore.json
# 2. 重启 Agent 进程
systemctl restart my-agent

注意:删除后对方公钥也变了——原对话方设备可能要触发”重新建立加密 通道”,这通常透明,偶尔需要重新发起。

详见 Agent 身份与密钥

AGENT_LIMIT_EXCEEDED

维度内容
HTTP403
Layer配额
SDK 自动恢复✗(业务侧调整)

触发场景:用户已达 50 Agent 创建上限。

根因:V1 默认每用户 50 个 Agent(后端 env 可配)。详见 Agent 开发者平台规范 §配额。

处理

用户视角:
1. 在 Hashee app 跟系统 Agent 说"列出我的 Agent" 看哪个不用了
2. 删掉不用的 → 名额释放
3. 重新创建
需要扩配额(V2 marketplace):
→ 联系 Hashee 开发者支持

RATE_LIMITED

维度内容
HTTP429
Layer限速
SDK 自动恢复✓(首次自动 backoff;多次后抛业务)

触发场景:触发任意端点的限速。error.params.retry_after_ms

  • Retry-After header 提供等待时长。

典型限速

  • Agent 消息发送:5 req/s/agent
  • 文件上传:5 req/s/agent
  • Capability Manifest 更新:1 req/min/agent
  • Token 旋转:5 req/24h

处理

async function sendWithBackoff(payload) {
try {
return await agent.send(convId, payload);
} catch (err) {
if (err.code === "RATE_LIMITED" || err.code === "MESSAGE_RATE_LIMITED") {
await sleep(err.retry_after_ms ?? 1000);
return agent.send(convId, payload); // 重试一次
}
throw err;
}
}

详见 速率限制与重试

RELATION_REVOKED

维度内容
HTTP403
Layer关系
SDK 自动恢复✗(业务清理 + 事件 handler)

触发场景:用户主动撤销了和你 Agent 的 H2A 关系。Agent 尝试给该 user 发 消息会触发;也会收到 relation.revoked 事件。

根因:用户在 Hashee app 中”删除联系人 + 撤销 Agent 所有授权”。

处理

agent.addEventHandler(async (event) => {
if (event.type !== "relation.revoked") return;
const { user_id, conversation_id } = event.payload;
// 1. 清理你存的对话明文
await db.deleteMessages({ conversation_id });
// 2. 清理用户档案 / 个性化数据
await db.deleteUserProfile({ user_id, agent_id: AGENT_ID });
// 3. 撤销外部资源
await externalApi.revokeUserAccess({ user_id });
// 4. 写本地审计日志
await audit.log({ action: "relation_revoked_handled", user_id });
});

详见 更新与撤销

ARTIFACT_REVISION_CONFLICT

维度内容
HTTP409
LayerArtifact
SDK 自动恢复✗(业务侧 reconcile + retry)

触发场景updateArtifact 调用的 based_on_revision 与后端当前 revision 不一致。

根因:并发 update 同一 artifact(如多 user 同时投票 + 多 replica 同时处理)。

处理

async function updateWithReconcile(artifactId, patchFn) {
for (let i = 0; i < 3; i++) {
const latest = await agent.getArtifact(convId, artifactId);
const next = patchFn(latest);
try {
return await agent.updateArtifact(convId, {
ref_artifact: artifactId,
based_on_revision: latest.revision,
artifact: { payload: next },
});
} catch (err) {
if (err.code !== "ARTIFACT_REVISION_CONFLICT") throw err;
// 拉最新再 reconcile
}
}
throw new Error("update conflict 3 retry exhausted");
}

详见 Artifact 高级 — 冲突处理

WEBHOOK_SIGNATURE_INVALID

维度内容
HTTP401
LayerWebhook
SDK 自动恢复✗(配置错)

触发场景:webhook 收到的 HMAC-SHA256 签名不匹配 — SDK / 你自己验签时抛。

根因

  1. HASHEE_WEBHOOK_SECRET 配错(staging vs prod 串号)
  2. secret 已旋转但你的服务未更新
  3. MITM / 重放攻击(极少)
  4. body 在 reverse proxy 处被修改(如自动添加 trailing newline)

处理

// 验签失败时 always 回 401(不让重试放大)
if (!await verifyWebhookSignature(secret, headers, body)) {
return new Response("invalid signature", { status: 401 });
}

详见 Webhook 协议

WEBHOOK_TIMESTAMP_SKEW

维度内容
HTTP400
LayerWebhook
SDK 自动恢复✗(服务器时间需校准)

触发场景X-Hashee-Timestamp 在 ±5 分钟容忍窗外。

根因:你的服务器时间漂移(VPS 无 NTP / Lambda 冷启动罕见 / Docker container 时钟错)。

处理

Terminal window
# Linux
sudo timedatectl set-ntp true
sudo systemctl restart systemd-timesyncd
# Docker
# Dockerfile: 安装 chrony 或 ntp 自启动

MANIFEST_TOO_LARGE

维度内容
HTTP413
LayerCapability Manifest
SDK 自动恢复✗(精简 manifest)

触发场景:Capability Manifest JSON 序列化后 > 128 KB hard cap。

根因

  1. 工具数量过多(>50 tools)
  2. input_schema 嵌套过深
  3. description_i18n_key 应该是 key 但写成了长文本

处理

  • 检查是否每个 tool 都需要完整 description(用 i18n key 而不是 inline 文本)
  • 把相似工具合并(用 enum + oneOf 替代多个独立 tool)
  • ≥ 64 KB 时后端 telemetry 已发 warning,及时响应

详见 Capability Manifest 规范 §2.3。

FILE_TOO_LARGE

维度内容
HTTP413
Layer文件
SDK 自动恢复✗(拆分文件)

触发场景:上传文件 > 100 MB hard cap。

根因:单文件硬上限 100 MB(V1)。

处理

  • 在你的 Agent 侧分块(chunk)
  • 用 Artifact + R2 外链方式替代直接 upload
  • 大量数据走数据库 / 外部 storage + 链接

WEBHOOK_PAYLOAD_TOO_LARGE

维度内容
HTTP413
LayerWebhook
SDK 自动恢复✓(应自动走 R2)

触发场景:webhook body > 1 MB hard cap。

根因:消息附带超大内容(不通过 R2 走)。

处理:通常你不该见到 — 后端会自动把 > 1 MB 的 payload 转为 R2 引用 发送 stub envelope。如果真见到,是后端 bug,请上报。

GRANT_REVOKED

维度内容
HTTP403
LayerGrant
SDK 自动恢复✗(业务清理)

触发场景:用户撤销了对应的数据访问 grant。

根因:用户在 Hashee app “Agent 详情 → 已授权数据” 里撤销 scope。

处理

agent.addEventHandler(async (event) => {
if (event.type !== "grant.revoked") return;
const { grant_id, scope, user_id } = event.payload;
// 立即清理:
// - 内存缓存
// - 已派生的衍生数据(向量化、指纹、AI 训练样本)
await db.deleteGrantData({ grant_id });
});

详见 Data Grants

AGENT_SUSPENDED / AGENT_BANNED

维度内容
HTTP403
Layer治理
SDK 自动恢复✗(断开 + 不重连)

触发场景:平台治理状态变更,Agent 被暂停或永久封禁。

根因

  • AGENT_SUSPENDED (L2):内容违规 / 用户投诉
  • AGENT_BANNED (L3):严重违规 / 重复违规

处理:SDK 自动断开;不重连。owner 应:

  1. GET /agents/:id/governance 看具体原因
  2. 联系平台申诉

DECRYPT_FAILURE

维度内容
HTTP
LayerE2EE
SDK 自动恢复✓(单条丢弃,不影响其他)

触发场景:SDK 上报某条消息无法解密。

根因枚举:

reason含义排查方向
signatureEd25519 验签失败发送者用错私钥 / Agent 持有的发送者公钥版本旧
no_wrap找不到给本 Agent 的 wrap发送时还没拿到 Agent 公钥(首次连接竞态)
unwrapunwrap CEK 失败Agent 私钥不匹配 / 密钥误改
aeadAES-GCM tag 不匹配AAD 不一致(如时钟严重不同步影响 epoch)
parse解密后不是合法 JSON协议版本不匹配(罕见)

处理

agent.addDecryptFailureHandler((report) => {
metrics.increment("hashee.decrypt_failure", { reason: report.reason });
if (report.reason === "unwrap" || report.reason === "signature") {
// 大概率密钥问题,报警人工介入
notifyOps("decrypt failure", report);
}
});

详见 SDK 安全与加密边界


全表参考

认证错误(4xx)

HTTP说明处理
UNAUTHORIZED401缺 / 无效 token重新走登录
TOKEN_EXPIRED401access token 5 min 过期/auth/refresh
AGENT_TOKEN_INVALID401Agent token 撤销 / 无效重新生成
TURNSTILE_FAILED403Cloudflare Turnstile 未通过让用户重新过验证
ACCOUNT_LOCKED4235 次登录失败锁 15 minretry_after
PASSKEY_VERIFICATION_FAILED401WebAuthn 签名验证失败让用户重试
EMAIL_VERIFICATION_REQUIRED403邮箱未验证/auth/send-code

权限错误(4xx)

HTTP说明处理
FORBIDDEN403通用权限不足
KEY_ENUMERATION_BLOCKED403没共享对话却查公钥不要预查;走真实路由
ARTIFACT_NOT_FORWARDABLE403artifact 设了 forwardable: falseUI 隐藏转发按钮
AGENT_RESTRICTED403Agent L1 治理限制检查 /agents/:id/governance
AGENT_SUSPENDED403Agent L2 治理暂停SDK 自动断开
AGENT_BANNED403Agent L3 治理永久封禁SDK 不重连
NOT_CONVERSATION_MEMBER_UPLOAD403非成员尝试上传
CONVERSATION_FORBIDDEN403Agent 不在 conv
GRANT_DENIED403Grant 被拒 / 已撤销业务 fallback
GRANT_EXPIRED403Grant 时间窗到期重新申请
GRANT_REVOKED403用户撤销 grant业务清理 + 不再访问
RELATION_REVOKED403用户撤销关系业务清理

验证错误(4xx)

HTTP说明
VALIDATION_ERROR400字段验证未通过
FORWARD_TARGET_LIMIT400转发超过 10 个目标
DEVICE_LIMIT_EXCEEDED400超过每账户 5 设备
SHA256_MISMATCH400文件上传密文 SHA-256 不匹配
MANIFEST_TOO_LARGE413Capability Manifest > 128 KB
WEBHOOK_PAYLOAD_TOO_LARGE413webhook body > 1 MB
FILE_TOO_LARGE413文件 > 100 MB
INVALID_ENVELOPE400wire envelope 解析失败
INVALID_SIGNATURE400Ed25519 签名验证失败

未找到错误(4xx)

HTTP说明
NOT_FOUND404通用资源不存在
USER_NOT_FOUND404user_id 不存在
GROUP_NOT_FOUND404group_id 不存在
CONVERSATION_NOT_FOUND404conv_id 不存在
MESSAGE_NOT_FOUND404message_id 不存在
AGENT_NOT_FOUND404agent_id 不存在
AGENT_NOT_REGISTERED404Agent 注册不完整
KEY_BACKUP_NOT_FOUND404用户未上传备份
MIGRATION_SESSION_EXPIRED404设备迁移信令 TTL 过期
INVITE_CODE_NOT_FOUND404邀请码不存在或已用

配额与冲突(4xx)

HTTP说明
AGENT_LIMIT_EXCEEDED403超过用户 50 Agent 配额
GROUP_KEY_VERSION_CONFLICT409群密钥并发轮换冲突
ARTIFACT_REVISION_CONFLICT409artifact_update revision 不匹配
MANIFEST_VERSION_CONFLICT409Capability Manifest 并发更新冲突
DEVICE_NAME_TAKEN409设备名重复
GROUP_KEY_ROTATION_LIMIT4296/h/conv 上限

速率限制(4xx)

HTTP说明处理
RATE_LIMITED429通用速率限制Retry-After
MESSAGE_RATE_LIMITED429消息发送 5 req/s/agent缓冲并节流
FILE_UPLOAD_RATE_LIMITED429文件上传 5 req/s/agent串行化
MANIFEST_UPDATE_RATE_LIMITED4291 req/min/agent合并改动
TOKEN_ROTATION_RATE_LIMITED4295 req/24h不要循环 rotate

超时与连接(4xx / 5xx)

HTTP说明
DEVICE_AUTH_TIMEOUT408设备授权 60s 超时
WEBHOOK_DELIVERY_TIMEOUT408Webhook 10s 内无响应
STREAM_TIMEOUT408流式 5 min 上限 / 30s 无 delta

Agent 加密相关

触发SDK 行为
AGENT_KEYS_MISMATCH客户端私钥与后端公钥不匹配throw;需 wipe local keystore
AGENT_PUBKEY_NOT_FOUND后端没找到 Agent 公钥极少见;联系支持
DECRYPT_FAILURESDK 上报某条消息无法解密走 decryptFailureHandler

Webhook 相关

触发
WEBHOOK_SIGNATURE_INVALIDHMAC 不匹配
WEBHOOK_TIMESTAMP_SKEWtimestamp ±5min 外
WEBHOOK_DELIVERY_DUPLICATEdelivery_id 24h 内已见过
WEBHOOK_PAYLOAD_INVALIDbody 解析失败
WEBHOOK_AGENT_UNREACHABLE7 次重试失败后状态机

Stream 错误

说明
stream_timeout5 分钟无 done
orphan_detected30 秒无 delta
client_offline客户端长时间断开(V2)
peer_revoked流式过程中关系被撤销
rate_limited流式限速触发

Stream 错误不自动重试——Agent 决定是否重新启动 stream session。

Tool Call denied.reason 枚举

artifact_response.payload.reasonstatus === "denied" 时给出:

reason说明
user_rejected用户主动拒绝
user_timeouthigh sensitivity 30s 超时
tool_not_supported_in_group群里 tool call 禁用
permission_revoked用户撤销了对应 permission_scope
tool_timeout客户端执行超 tool.timeout_ms
tool_not_implemented客户端不支持此 tool

HTTP 状态码汇总

含义
200成功
201创建
204成功无 body
400验证 / 参数错
401认证失败
403权限拒
404未找到
408超时
409冲突
413Payload 过大
423账户锁
429速率限制
500内部错
502 / 503 / 504临时不可用,按 Retry-After 重试

错误处理代码模板

async function callApi<T>(fn: () => Promise<T>): Promise<T> {
try {
return await fn();
} catch (err: any) {
switch (err.code) {
case "TOKEN_EXPIRED":
await refreshToken();
return fn();
case "RATE_LIMITED":
case "MESSAGE_RATE_LIMITED":
await sleep(err.retry_after_ms ?? 1000);
return fn();
case "AGENT_KEYS_MISMATCH":
notifyOps("agent keys mismatch", { agent_id: AGENT_ID });
throw err;
case "GRANT_REVOKED":
case "RELATION_REVOKED":
await cleanupForUser(...);
throw err;
default:
throw err;
}
}
}

相关页面