常見問題與排查
先記錄 SDK 版本、Node.js 版本、code、reason、op 和 requestId,再對照以下場景。錯誤提示文本不作為程式分支條件,示例見錯誤處理。
安裝與執行
node --version
npm config get registry
npm view @deeprespond/im-server-sdk@1.0.7 version --registry=https://registry.npmjs.org/| 現象 | 處理 |
|---|---|
| npm 404 或 ETARGET | 包名為 @deeprespond/im-server-sdk,當前公開版本 1.0.7。私有映象可能尚未同步,使用下方官方 registry 安裝命令 |
| Unsupported engine | Node.js 至少為 22.17.0;在實際執行服務的容器或程序中檢查版本 |
| Cannot use import outside a module | JavaScript 使用 .mjs,或在 package.json 中設定 type: module;CommonJS 使用 require() |
| 找不到示例中的 client.js | TypeScript 示例先按 NodeNext 編譯,再執行生成的 JavaScript,見示例指南 |
| TypeScript 找不到子路徑型別 | 使用 moduleResolution: NodeNext、node16 或 bundler;安裝 @types/node@22,不要使用舊 node10 解析方式 |
| 瀏覽器或 Edge 中構造客戶端失敗 | 該包使用服務端憑據和 Node.js 能力;Next.js 路由配置 runtime = 'nodejs',網頁改用客戶端 Web SDK |
npm install @deeprespond/im-server-sdk@1.0.7 --registry=https://registry.npmjs.org/以上命令只為本次安裝指定 registry,不修改專案或全域性 npm 配置。
憑據與身份
| 名稱 | 從哪裡取得 | 用在哪裡 |
|---|---|---|
AppKey:組織名 # 應用名 | 控制台應用資訊 | 分別傳給 orgName、appName |
| Client ID、Client Secret | 控制台服務端憑據 | 建立 DRClient,由 SDK 換取 App Token |
| App Token | SDK 自動換取、快取和重新整理 | 應用管理員身份呼叫 OpenAPI,不交給終端使用者 |
| 使用者登入憑證 ticket | 後端為已認證業務使用者呼叫 users.issueLoginTicket() | 交給該使用者的客戶端 SDK 登入 |
| 回撥 endpoint ID、簽名金鑰 | 控制台回撥配置 | CallbackHandler.secrets,與 Client Secret 分開管理 |
服務端 SDK 具有應用管理許可權。業務後端需要自己校驗使用者身份和操作許可權,例如不能讓請求中的任意 username 直接決定給誰簽發 ticket;管理撤回和管理歷史查詢也不能直接當作普通使用者介面。
鑑權與網路
| 現象 | 核對順序 |
|---|---|
unauthenticated 或首次請求換令牌失敗 | baseUrl 指向正確環境;組織名、應用名、Client ID/Secret 來自同一應用;憑據未被撤銷;錯誤的 op 是否為 app.token |
client_unavailable | 檢視 reason 和 details.cause;暫時故障可能處於冷卻期。應用已刪除或租戶已登出時,isPermanentlyUnavailable 為 true,繼續重試不能恢復 |
permission_denied | 核對應用狀態、介面所需功能或策略,並按該 REST 介面的 details 排查 |
network_error | 檢查目標域名、埠、容器網路、DNS、代理及證書鏈;不要把控制台網頁地址誤作 API 根地址 |
| HTTPS_PROXY 已設定但仍直連 | SDK 不自行讀取環境代理,使用自定義 fetch/ProxyAgent;見代理與私有證書 |
| 私有 CA 證書校驗失敗 | 在啟動程序前設定 NODE_EXTRA_CA_CERTS,保證證書檔案在服務容器內可讀;保留 TLS 校驗 |
更新應用憑據時呼叫 im.updateCredentials(newClientId, newClientSecret),或更新配置並重啟程序;不要在日誌中列印 Secret、App Token、ticket 或帶簽名的下載地址。
超時、限流與重複操作
| 現象 | 含義與處理 |
|---|---|
timeout | 單次嘗試或整次呼叫到期,或 AbortSignal.timeout() 觸發。先核對 timeoutMs 與 totalTimeoutMs,兩者均為毫秒 |
canceled | 呼叫方主動取消,或原客戶端正在關閉;按業務需要終止本次流程 |
rate_limited | SDK 已按配置等待或達到等待上限。error.retryAfter 為秒;maxRetryAfterMs 為毫秒,不要混用 |
| 寫請求超時後不知道是否成功 | 先查詢服務端結果;同一業務重試複用訊息 client_msg_id 或頻道 operation_id,不要每次生成新值 |
| HTTP 成功但批次有失敗 | 檢查 result.ok、failed_items;呼叫 throwIfFailed() 可丟擲 BatchError,逐項處理失敗原因 |
version_conflict | 重新讀取當前物件版本,再由業務決定是否更新;不要無條件覆蓋並重復提交 |
isTemporary 表示錯誤通常可恢復,不表示任意寫操作都可以安全重發。SDK 的自動重試分類見方法參考,業務任務重試仍需保持冪等標識。
回撥接入
先完成“建立地址 → 啟動接收端 → 驗證地址”,再觸發對應事件。服務端能夠訪問接收端地址才有效,本機瀏覽器能訪問並不能證明遠端可達。
| HTTP 狀態或現象 | 排查 |
|---|---|
| 401 | endpoint ID、金鑰陣列、系統時間和原始請求體;同一個帶簽名請求重複傳送會被防重放檢查拒絕 |
| 400 | 簽名通過但請求結構不符合協議;檢視接收端日誌,不把普通業務 JSON 直接傳送到回撥端點 |
| 413 | 同時檢查反向代理、框架 body parser、SDK 的 maxBodyBytes;預設 SDK 上限為 2 MiB |
| 503 | 金鑰查詢、Redis 或業務處理失敗,事件正在被另一例項處理,或同步回撥超時;檢視 handler 日誌 |
| Express 驗籤失敗 | 回撥路由放在 express.json() 前,或保留原始 Buffer;不能把解析後的物件重新 JSON.stringify 代替原文 |
| Next.js 本地成功、線上重複處理 | 檢查是否部署為多個例項;統一使用共享 Redis 和相同 keyPrefix,避免各例項只在記憶體去重 |
| 事件 204,但業務處理函式沒執行 | 核對訂閱和註冊的事件名;未知事件或未註冊的已知事件可能被忽略。需要統一觀察時使用 onAny() |
| 同步回撥 200,但預期策略沒生效 | 檢查返回的 SDK Verdict、實際啟用的同步鉤子和服務端配置;同步回撥與事件訂閱分開設定 |
回撥有重投語義。業務寫入成功後進程退出,仍可能再次收到同一事件;資料庫寫入或入隊操作也應按事件 ID 冪等。共享儲存和處理時限見接收回調。
檔案與獨立頻道
上傳時普通檔案的記憶體來源需要 name,群檔案需要 group_id,使用者頭像需要 owner。SDK 不支援以 Readable 流作為可重讀的上傳來源,先落盤或使用 Buffer/Blob。下載傳媒體 url,SDK 負責換取臨時下載地址,見檔案上傳與下載。
client.channels 管理獨立 RTC 頻道;client.calls 管理 IM 通話。建立頻道、簽發頻道票據後,使用者仍需通過對應客戶端 API 加入媒體。頻道分頁使用 next_cursor,沒有 channels.iter();修改頻道和封禁操作所需的版本欄位見頻道參考。
提交排查資訊
向運維或技術支援提供發生時間及其時區、環境、SDK/Node 版本、介面名、錯誤碼和 requestId。附上經過脫敏的最小呼叫程式碼即可,保留實際欄位名和超時配置;憑據和使用者登入票據不隨排查資訊傳送。
