# 错误码与故障排查

> iKho Embedded 平台接口的统一错误响应结构、HTTP 状态语义、按 API 分组的错误码,以及带 request_id 的排查流程。

本页错误码为内测契约,以联调时提供的正式文档为准。SDK 层错误码(设备扫描、绑定、同步)见 [iOS SDK](/docs/embedded/ios-sdk/) 的「错误码」一节。

## 统一错误响应结构

平台接口出错时,响应体为统一的 JSON 结构:`code` 是机器可读的错误码,`message` 是面向开发者的中文说明,`request_id` 是本次请求的唯一标识。程序里请只依赖 `code` 做分支判断,不要匹配 `message` 文案;`request_id` 用于联系支持时定位日志。

  错误响应示例(内测契约,以联调为准)
    
  

  
```
{
  "code": "IKHO_ERR_TOKEN_EXPIRED",
  "message": "访问令牌已过期,请重新获取。",
  "request_id": "req_9f3c1a2b7d"
}
```

## HTTP 状态语义

HTTP 状态码给出错误的大类,响应体里的 `code` 给出具体原因。两者配合定位问题。

| 状态码 | 语义 | 典型场景 |
|---|---|---|
| `400` | 请求参数错误 | 缺少必填字段、字段格式不合法、取值超出允许范围 |
| `401` | 未认证 | 凭证缺失、令牌无效或已过期、应用被停用 |
| `403` | 已认证但受限 | 免费转写额度已用尽(`IKHO_ERR_QUOTA_EXCEEDED`) |
| `404` | 资源不存在 | 转写任务、上传会话或接口路径找不到 |
| `413` | 文件过大 | 上传文件或单个分片超出内测期大小上限(`IKHO_ERR_FILE_TOO_LARGE`) |
| `429` | 请求频率超限或并发受限 | 轮询过密触发限流(`IKHO_ERR_RATE_LIMITED`),或并发转写任务过多(`IKHO_ERR_CONCURRENCY_LIMITED`);两者都带 `Retry-After` 响应头 |
| `5xx` | 服务端错误 | 平台内部异常(`IKHO_ERR_INTERNAL`),可按指数退避重试;持续出现请携 `request_id` 联系支持 |

## 认证 API 错误码

见[认证 API 总览](/docs/api-reference/auth/overview/)。多数认证错误可以在你的后端自动恢复:令牌过期重签即可,不要把 `secret` 下发到端上重试。应用被停用时,换取合作方令牌会返回 `IKHO_ERR_INVALID_CLIENT`(401),已签发令牌继续调用则返回 `IKHO_ERR_TOKEN_INVALID`(401);令牌类型不符(如拿合作方令牌调用户级接口)返回 `IKHO_ERR_TOKEN_INVALID`(401)。

| 错误码 | 状态码 | 含义 | 建议处理 |
|---|---|---|---|
| `IKHO_ERR_INVALID_CLIENT` | 401 | `client_id` 或 `secret` 不正确,或应用已被停用 | 核对开通邮件里的凭证;确认 Basic 值为 `base64(client_id:secret)` 且不含换行;应用状态异常时携 `request_id` 联系对接工程师 |
| `IKHO_ERR_TOKEN_EXPIRED` | 401 | 访问令牌已过期 | 合作方令牌用 `refresh_token` 续期;用户令牌由后端重签后调用 `setUserToken` 下发 |
| `IKHO_ERR_TOKEN_INVALID` | 401 | 访问令牌无效或类型不符(含应用被停用、令牌级别用错) | 确认传入的是完整、未截断的令牌,`Bearer` 与令牌之间只有一个空格;按接口要求使用对应级别的令牌 |
| `IKHO_ERR_REFRESH_INVALID` | 401 | `refresh_token` 无效、已使用或已过期 | 用 `client_id` 与 `secret` 重新走一遍获取合作方令牌流程 |
| `IKHO_ERR_API_KEY_INVALID` | 401 | `X-Client-Id` 或 `X-Client-Api-Key` 不正确 | 转写 API 用这两个密钥头鉴权(不同于 OAuth 令牌);核对开通时下发的 `client_id` 与 `api_key` |
| `IKHO_ERR_USER_ID_INVALID` | 400 | `user_id` 不符合 6 到 120 个字符的要求 | 用你系统里对该用户的稳定标识,并校验长度 |

## 文件上传 API 错误码

见[文件上传 API 总览](/docs/api-reference/file/overview/)。分片上传的常见失败点在合并这一步:分片没传全、`ETag` 没存对,合并就会返回 `IKHO_ERR_UPLOAD_PARTS_INVALID`(400)。

| 错误码 | 状态码 | 含义 | 建议处理 |
|---|---|---|---|
| `IKHO_ERR_FILE_TYPE_UNSUPPORTED` | 400 | `filetype` 不在支持范围 | 只支持 `mp3`、`m4a`、`wav`,转换格式后重新上传 |
| `IKHO_ERR_FILE_TOO_LARGE` | 413 | 文件或单个分片超出大小上限 | 上限内测期以联调口径为准;超限文件请切分录音或压缩码率后重试 |
| `IKHO_ERR_UPLOAD_NOT_FOUND` | 404 | 上传会话不存在或已失效 | 重新调用生成预签名地址,开启新的上传会话并重传全部分片 |
| `IKHO_ERR_UPLOAD_PARTS_INVALID` | 400 | 分片信息不完整或与上传会话不匹配 | 核对每个分片的 `PUT` 是否成功、`ETag` 是否按响应头原样保存,补齐后再合并 |

## 转写 API 错误码

见[转写 API 总览](/docs/api-reference/transcription/overview/)。注意区分两类失败:提交或查询接口直接报错(本表),与任务进入 `FAILURE` 终态(任务受理成功但处理失败,不再单列错误码,原因请携 `request_id` 联系支持)。

| 错误码 | 状态码 | 含义 | 建议处理 |
|---|---|---|---|
| `IKHO_ERR_FILE_URL_NOT_ALLOWED` | 400 | `file_url` 不被接受 | 内测期 `file_url` 仅接受本平台文件上传 API 返回的 `DownloadUrl`;重新走合并分片换取新地址后再提交 |
| `IKHO_ERR_TASK_NOT_FOUND` | 404 | `transcription_id` 对应的任务不存在 | 核对任务标识是否完整,以及查询用的密钥头与提交时是否一致 |
| `IKHO_ERR_QUOTA_EXCEEDED` | 403 | 免费转写额度已用完 | 免费额度为 300 小时转写;超出部分请联系对接工程师提升额度 |
| `IKHO_ERR_CONCURRENCY_LIMITED` | 429 | 并发转写任务数已达上限 | 等待现有任务完成再提交;响应带 `Retry-After` 头,按其指示等待后重试 |

## 通用错误码

以下错误码不限定单个 API,任何接口都可能返回。

| 错误码 | 状态码 | 含义 | 建议处理 |
|---|---|---|---|
| `IKHO_ERR_BAD_REQUEST` | 400 | 请求参数不合法 | 按接口文档核对必填字段与取值范围;错误 `message` 会指出具体问题 |
| `IKHO_ERR_RATE_LIMITED` | 429 | 请求频率超出当前配额 | 遵守响应里的 `Retry-After` 头,拉长间隔并加指数退避后重试 |
| `IKHO_ERR_NOT_FOUND` | 404 | 接口不存在 | 核对请求路径与文档 [ikho.cn/docs](https://ikho.cn/docs) 是否一致 |
| `IKHO_ERR_INTERNAL` | 500 | 服务暂时不可用 | 按指数退避重试;若持续失败请携 `request_id` 联系支持 |

## SDK 端错误与 API 错误的对应关系

Embedded SDK 的错误码(`IKhoError`)与本页的平台错误码是同一套 `IKHO_ERR_*` 命名下的两层:设备侧错误(如 `IKHO_ERR_BLE_UNAVAILABLE`、`IKHO_ERR_BIND_OCCUPIED`、`IKHO_ERR_WIFI_HANDSHAKE`)发生在手机与 S1 之间,只会出现在 SDK 回调里,不会出现在 REST 响应中;而 SDK 内部调用平台接口失败时,会把平台错误映射为 SDK 错误抛出,并在错误对象里保留底层的 `code` 与 `request_id`。最常见的一条对应是:平台返回 401(`IKHO_ERR_TOKEN_INVALID` 或 `IKHO_ERR_TOKEN_EXPIRED`)时,SDK 侧统一表现为 `IKHO_ERR_UNAUTHORIZED`,处理方式都是由你的后端重签用户令牌后调用 `setUserToken`。排查 SDK 报错时,先看错误对象里有没有 `request_id`:有,说明问题出在平台接口,按本页错误码处理;没有,说明问题出在设备连接,按 [iOS SDK](/docs/embedded/ios-sdk/) 的错误码表处理。

## 排查流程

自查无法解决时,按下面三步整理信息再联系支持,能明显缩短定位时间。

  
    1

    拿到 request_id
从错误响应体或 SDK 错误对象里取出 `request_id`。没有 `request_id` 的设备侧错误,改为记录设备序列号与复现步骤。

  

  
    2

    记录时间点与 client_id 前 6 位
记下报错发生的时间(精确到分钟)与你的 `client_id` 前 6 位。不要在任何渠道发送完整的 `secret` 或 `api_key`。

  

  
    3

    联系支持
把 `request_id`、时间点、`client_id` 前 6 位与错误码一并发给对接工程师,见[联系我们](/docs/mcp-cli/contact/)。

  

## 常见故障速查

| 症状 | 常见原因 | 处置 |
|---|---|---|
| 获取合作方令牌一直 401 | Basic 值拼装错误,`base64(client_id:secret)` 里混入了换行或空格 | 重新编码并确认冒号分隔、无换行;核对凭证来自开通邮件 |
| 用户令牌每天固定时间失效 | 用户令牌有效期约 24 小时,后端没有在过期前重签 | 后端提前重签,SDK 侧调用 `setUserToken` 更新,无需重新配置 |
| 分片 `PUT` 返回 403 | 预签名地址已过期,或把分片传到了错误序号的地址 | 重新生成预签名地址;按 `PartNumber` 与地址一一对应上传 |
| 合并分片返回 `IKHO_ERR_UPLOAD_PARTS_INVALID`(400) | 有分片未成功上传,或 `ETag` 没有按响应头原样保存 | 核对 `part_list` 的数量与 `ETag`,补传缺失分片后重新合并 |
| 提交转写报 `IKHO_ERR_FILE_URL_NOT_ALLOWED`(400) | `file_url` 不是本平台文件上传 API 返回的 `DownloadUrl`,或对应文件未完成上传 | 用合并分片返回的 `DownloadUrl` 作为 `file_url`;地址失效则重新走合并流程换取新地址 |
| 任务长时间停在 `PROGRESS` | 音频较长或队列繁忙 | 继续轮询并加大间隔;远超预期时携 `request_id` 联系支持 |
| 任务进入 `FAILURE` 但音频能正常播放 | 音频编码异常、静音占比过高或内容无有效语音 | 用标准编码重新导出 `mp3`、`m4a` 或 `wav` 后重试;仍失败携 `request_id` 联系支持 |
| 频繁收到 429 | 轮询间隔过短或并发提交过多 | 拉长轮询间隔、加指数退避、控制并发;限流阈值内测期以联调口径为准 |

## 下一步

[iOS SDK 错误码 设备扫描、绑定、同步等设备侧错误码与建议处理。 打开 iOS SDK](/docs/embedded/ios-sdk/)

[联系我们 整理好 `request_id`、时间点与错误码,交给对接工程师定位。 联系支持](/docs/mcp-cli/contact/)
