MatchRPG 錯誤碼架構澄清與 Dungeon 重新編號(含碰號問題)¶
文檔資訊
- 分類: architecture
- 難度: advanced
- 預估閱讀時間: 8 分鐘
- 標籤:
error-codes,twirp,dungeon,dead-code,proto,documentation-governance,range-collision
摘要¶
本次 session 釐清了 MatchRPG Server 的錯誤碼架構為單通道設計(Twirp meta.error_code),確認 commonv1.ErrorCode 是 dead enum,完成 Dungeon 錯誤碼從 1-20 重新編號到 3000-3099,並發現 3000-3099 與通用錯誤碼區段碰號的 P0 問題。同時比對 PD 規格文件與最新設計的差異,識別出語意錯誤和缺漏的 Sticker 模組。
關鍵學習¶
-
Twirp meta.error_code 是唯一實際使用的錯誤碼通道,proto enum 不做 wire serialization
-
commonv1.ErrorCode enum 是 dead code(0 個 runtime consumer),ErrorHandlingReference.md 描述的是這個死掉的 enum
-
Dungeon 錯誤碼從兩位數 1-20 改到 3000-3099 是安全的(因為 string emit,非 wire integer),但 3000-3099 範圍與 common errors proto 3001-3504 碰號
-
PD 規格 v0.0.20 完全缺少 Sticker 模組(11 個 user-facing codes 5001-5031),且 Dungeon 仍用舊 1-20 編號
-
文檔治理:TODO_ 前綴可豁免 check-doc-metadata.ps1 lint 檢查
-
回應應該先讀設計文檔(doc 33)再回答,不能憑假設回答架構問題
技術細節¶
錯誤碼架構(單通道設計)¶
MatchRPG Server 的錯誤碼設計是**單通道**:
pkg/errors/AppError 存在,但只被 HTTP middleware 層使用(auth/idempotency/signature/sequence/ratelimit),是平行的 JSON ErrorResponse 路徑,不是 Twirp meta 的雙層設計。
Dead Code 確認¶
api/proto/matchrpg/common/v1/errors.proto 的 commonv1.ErrorCode enum:
- 0 個 runtime consumer(grep 確認)
- ErrorHandlingReference.md(Unity proto repo)描述的是這個死掉的 enum,具有誤導性
- Proto enum integer 不做 wire serialization(只用 string emit),所以重新編號是安全的
Dungeon 重新編號¶
變更前:Dungeon 錯誤碼 1–20(兩位數,與其他模組格式不一致)
變更後:Dungeon 錯誤碼 3001–3020
// 修改前
NOT_FOUND = 1;
INSUFFICIENT_STAMINA = 2;
// ...
// 修改後
NOT_FOUND = 3001;
INSUFFICIENT_STAMINA = 3002;
// ...
修改了:
- api/proto/matchrpg/dungeon/v1/dungeon_errors.proto
- internal/modules/dungeon/dungeon_twirp.go(所有 WithMeta("error_code", "N") 字串)
碰號問題(P0)¶
後來發現:3000-3099 範圍與通用錯誤碼碰號:
- TODO_pd_error_code_translation.md:214:通用錯誤碼已占用 3001-3504
- api/proto/matchrpg/common/v1/errors.proto:40:雖然是 dead enum,但仍可能誤導維護者
建議:Dungeon 應改到不衝突的區段,需要重新評估。
PD 規格差異¶
PD_ErrorCode_TranslationSpec.md v0.0.20(2026-03-23)vs doc 33 v2.2(2026-04-07):
| 差異類型 | 數量 | 說明 |
|---|---|---|
| Sticker 完全缺漏 | 11 個 | 5001-5031 不在 PD 規格 |
| Dungeon 舊編號 | 20 個 | 仍用 1-20,需改為 3001-3020 |
| P1 語意錯誤 | 1 個 | 2032:PD 寫「含非法字元」,實際是長度限制 |
| P2 過於 generic | 4 個 | 2042/2043/2069 等寫「操作失敗請重試」 |
| 措辭風格差異 | ~10 個 | PD/UX 自行決定 |
What Changed¶
文檔變更¶
docs/33_Error_Codes.md 從 v2.0 升版到 v2.2:新增 §6 Sticker 區段(5 個子節),更新 §1.1 range table,§4 Dungeon table 全部從 1-20 更新為 3001-3020,新增 §4.1 舊→新對照表。
新建 docs/TODO_pd_error_code_translation.md:87 個錯誤碼條目(4 個已配置 + 83 個待 PD 配置),9 個子表按模組分類。
程式碼變更¶
dungeon_errors.proto 和 dungeon_twirp.go 完成重新編號,build 和 tests 均通過。pkg/pb/matchrpg/dungeon/v1/dungeon_errors.pb.go(generated file)尚未重新生成,需要 make proto。
命名決策¶
Enums_ResourcesType_PlayerPhysicalStrength = 8 → 改名為 Stamina = 8,新增 EtherHourglass = 9。需要 PD 更新 Luban xlsx。
So What¶
這次 session 澄清了一個長期存在的架構誤解:commonv1.ErrorCode 和 ErrorHandlingReference.md 描述的是 dead code,不是實際運行的錯誤碼系統。實際系統只有一個通道(Twirp meta.error_code string)。
Dungeon 重新編號雖然完成了,但後來發現 3000-3099 碰號,這是一個需要進一步處理的 P0 問題,不能就此收案。PD 規格的差異分析(特別是 2032 的語意錯誤)如果不修正,會導致用戶看到錯誤的錯誤訊息描述。
Trade-offs¶
- 重新編號安全性:因為是 string emit 非 wire integer,重新編號不影響協議相容性;但已生成的 pb.go 和 Unity CS 檔案需要 regenerate
- 3000-3099 碰號:快速修復時選了一個方便的範圍,但事後發現與通用錯誤碼碰號,需要再次移動
- Dead enum 保留:
commonv1.ErrorCode雖然是 dead code,但刪除前需要確認沒有外部依賴(Unity 客戶端可能有 literal 比對) - PD 規格 rebase:建議 PD 直接從
TODO_pd_error_code_translation.md重新對齊,而非在舊規格上 patch
Try It Fast¶
# 確認 commonv1.ErrorCode 是否真的沒有 runtime consumer
grep -r 'commonv1\.ErrorCode\|ErrorCode_' internal/ pkg/ cmd/ --include='*.go' | grep -v '_test\.go'
# 確認 Dungeon twirp.go 的錯誤碼已更新
grep 'error_code' internal/modules/dungeon/dungeon_twirp.go
# Build 驗證
go build ./internal/modules/dungeon/...
go test ./internal/modules/dungeon/... -count=1
# 確認 3000-3099 碰號範圍
grep -n '3[0-9][0-9][0-9]' api/proto/matchrpg/common/v1/errors.proto
Recommendation¶
- 立即處理碰號:Dungeon 3000-3099 碰號問題 — 需要選擇不衝突的區段(例如 7000-7099),重新修改 proto、twirp.go 和相關文檔
- PD 重新對齊:PD 應以
TODO_pd_error_code_translation.md為基準重新配置 87 個錯誤碼,特別修正 2032 的語意錯誤(長度限制,不是非法字元) - Proto Regen:從 Windows toolchain 執行
make proto重新生成dungeon_errors.pb.go,Unity 端同步 regenerateDungeonErrors.cs - Luban xlsx 更新:PD 將
PlayerPhysicalStrength = 8改名為Stamina = 8,新增EtherHourglass = 9 - 未來規範:分配新模組錯誤碼區段前,先 grep 確認範圍無衝突(doc 33 §1.1 range table 是 SoT)