{"record":{"id":"4f07cada74b5580e","repo":"chenhg5/cc-connect","slug":"tuitui-history-errcode-d-errmsg-s","errorCode":null,"errorMessage":"tuitui: history errcode=%d errmsg=%s","messagePattern":"tuitui: history errcode=(.+?) errmsg=(.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/tuitui/history.go","lineNumber":74,"sourceCode":"\taddHistoryOptions(payload, opts)\n\n\tapiPath := \"/robot/message/group/sync\"\n\tif chatType == chatTypeDirect {\n\t\tapiPath = \"/robot/message/single/sync\"\n\t}\n\tvar out struct {\n\t\tErrCode int              `json:\"errcode\"`\n\t\tErrMsg  string           `json:\"errmsg\"`\n\t\tCursor  string           `json:\"cursor\"`\n\t\tHasMore bool             `json:\"has_more\"`\n\t\tTime    any              `json:\"time\"`\n\t\tMsgs    []map[string]any `json:\"msgs\"`\n\t}\n\tif err := p.postJSON(ctx, apiPath, payload, &out); err != nil {\n\t\treturn nil, err\n\t}\n\tif out.ErrCode != 0 {\n\t\treturn nil, fmt.Errorf(\"tuitui: history errcode=%d errmsg=%s\", out.ErrCode, out.ErrMsg)\n\t}\n\treturn &HistoryResult{\n\t\tErrCode:     out.ErrCode,\n\t\tErrMsg:      out.ErrMsg,\n\t\tCursor:      out.Cursor,\n\t\tHasMore:     out.HasMore,\n\t\tCurrentTime: out.Time,\n\t\tMessages:    cleanHistoryMessages(out.Msgs),\n\t}, nil\n}\n\nfunc (p *Platform) fetchChannelHistory(ctx context.Context, chatID string, opts HistoryOptions) (*HistoryResult, error) {\n\tparsed := map[string]string{}\n\tif strings.HasPrefix(chatID, \"teams_\") {\n\t\tparsed = teamsParseChatID(chatID)\n\t} else {\n\t\tparsed[\"channel_id\"] = chatID\n\t}","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/tuitui/history.go#L56-L92","documentation":"The TuiTui direct/group history API returned a non-zero errcode in a 200-style response body, meaning the request reached the server but the backend rejected the operation. The API's errmsg is included verbatim. Common errcodes include auth/token failures and invalid chat IDs.","triggerScenarios":"Calling fetchDirectOrGroupHistory (via FetchHistory with chatType direct or group) where the response JSON has out.ErrCode != 0 — e.g. expired access_token, chat the bot is not a member of, or deleted chat ID.","commonSituations":"Bot credentials rotated but token not refreshed; fetching history for a chat ID from before the bot was removed; TuiTui backend maintenance returning business errors.","solutions":["Read errmsg in the error — it names the backend reason; handle the specific errcode accordingly.","Refresh the bot's access token if the errcode indicates auth failure.","Verify the bot is still a member of the chat and the chat ID is current.","Call p.postJSON-based auth refresh / re-login then retry once."],"exampleFix":"// before\nif out.ErrCode != 0 { return nil, fmt.Errorf(\"tuitui: history errcode=%d errmsg=%s\", out.ErrCode, out.ErrMsg) }\n// after\nif out.ErrCode == tokenExpiredCode {\n    if err := p.refreshToken(ctx); err != nil { return nil, err }\n    return p.fetchDirectOrGroupHistory(ctx, chatID, chatType, opts)\n}\nif out.ErrCode != 0 { return nil, fmt.Errorf(\"tuitui: history errcode=%d errmsg=%s\", out.ErrCode, out.ErrMsg) }","handlingStrategy":"retry","validationCode":"if !p.isAuthenticated(ctx) { if err := p.refreshToken(ctx); err != nil { return err } }","typeGuard":null,"tryCatchPattern":"res, err := p.FetchHistory(ctx, chatID, \"group\", opts)\nif err != nil {\n    var apiErr *TuiTuiAPIError\n    if errors.As(err, &apiErr) && apiErr.Code == tokenExpiredCode {\n        if rerr := p.refreshToken(ctx); rerr == nil {\n            res, err = p.FetchHistory(ctx, chatID, \"group\", opts)\n        }\n    }\n}","preventionTips":["Implement automatic token refresh on auth errcodes","Check bot membership before querying history for a chat","Log errcode+errmsg pairs to build an errcode handling table","Apply bounded retries for transient backend errcodes"],"tags":["tuitui","api","history"],"backgroundTag":"api-error-response","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}