chenhg5/cc-connect · error

tuitui: history errcode=%d errmsg=%s

Error message

tuitui: history errcode=%d errmsg=%s

What it means

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.

Source

Thrown at platform/tuitui/history.go:74

	addHistoryOptions(payload, opts)

	apiPath := "/robot/message/group/sync"
	if chatType == chatTypeDirect {
		apiPath = "/robot/message/single/sync"
	}
	var out struct {
		ErrCode int              `json:"errcode"`
		ErrMsg  string           `json:"errmsg"`
		Cursor  string           `json:"cursor"`
		HasMore bool             `json:"has_more"`
		Time    any              `json:"time"`
		Msgs    []map[string]any `json:"msgs"`
	}
	if err := p.postJSON(ctx, apiPath, payload, &out); err != nil {
		return nil, err
	}
	if out.ErrCode != 0 {
		return nil, fmt.Errorf("tuitui: history errcode=%d errmsg=%s", out.ErrCode, out.ErrMsg)
	}
	return &HistoryResult{
		ErrCode:     out.ErrCode,
		ErrMsg:      out.ErrMsg,
		Cursor:      out.Cursor,
		HasMore:     out.HasMore,
		CurrentTime: out.Time,
		Messages:    cleanHistoryMessages(out.Msgs),
	}, nil
}

func (p *Platform) fetchChannelHistory(ctx context.Context, chatID string, opts HistoryOptions) (*HistoryResult, error) {
	parsed := map[string]string{}
	if strings.HasPrefix(chatID, "teams_") {
		parsed = teamsParseChatID(chatID)
	} else {
		parsed["channel_id"] = chatID
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Read errmsg in the error — it names the backend reason; handle the specific errcode accordingly.
  2. Refresh the bot's access token if the errcode indicates auth failure.
  3. Verify the bot is still a member of the chat and the chat ID is current.
  4. Call p.postJSON-based auth refresh / re-login then retry once.

Example fix

// before
if out.ErrCode != 0 { return nil, fmt.Errorf("tuitui: history errcode=%d errmsg=%s", out.ErrCode, out.ErrMsg) }
// after
if out.ErrCode == tokenExpiredCode {
    if err := p.refreshToken(ctx); err != nil { return nil, err }
    return p.fetchDirectOrGroupHistory(ctx, chatID, chatType, opts)
}
if out.ErrCode != 0 { return nil, fmt.Errorf("tuitui: history errcode=%d errmsg=%s", out.ErrCode, out.ErrMsg) }
Defensive patterns

Strategy: retry

Validate before calling

if !p.isAuthenticated(ctx) { if err := p.refreshToken(ctx); err != nil { return err } }

Try / catch

res, err := p.FetchHistory(ctx, chatID, "group", opts)
if err != nil {
    var apiErr *TuiTuiAPIError
    if errors.As(err, &apiErr) && apiErr.Code == tokenExpiredCode {
        if rerr := p.refreshToken(ctx); rerr == nil {
            res, err = p.FetchHistory(ctx, chatID, "group", opts)
        }
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/4f07cada74b5580e. Report an issue: GitHub.