chenhg5/cc-connect · error
tuitui: invalid chat type %q
Error message
tuitui: invalid chat type %q
What it means
reactToMessage builds the /robot/message/custom/modify payload per chat type (direct, group, channel). If rctx.chatType is none of the known constants it cannot fill the right recipient field and rejects the request before any network call. chatType is usually derived from the reply context or guessed via guessChatType(chatID), so an empty/garbage value signals a bad reply context.
Source
Thrown at platform/tuitui/tuitui.go:657
payload := map[string]any{
"msgtype": "emoji_reaction",
"tousers": []map[string]string{},
"togroups": []map[string]string{},
"toteams": []map[string]string{},
"emoji_reaction": map[string]any{"emoji": emoji, "cancel": false},
}
switch rctx.chatType {
case chatTypeDirect:
payload["tousers"] = []map[string]string{{"user": rctx.chatID, "msgid": rctx.messageID}}
case chatTypeGroup:
payload["togroups"] = []map[string]string{{"group": rctx.chatID, "msgid": rctx.messageID}}
case chatTypeChannel:
team := teamsParseChatID(rctx.chatID)
team["parent_id"] = ""
team["post_id"] = rctx.messageID
payload["toteams"] = []map[string]string{team}
default:
return fmt.Errorf("tuitui: invalid chat type %q", rctx.chatType)
}
return p.postJSON(ctx, "/robot/message/custom/modify", payload, nil)
}
func (p *Platform) sendMediaID(ctx context.Context, rctx replyContext, mediaID, filename string, isImage bool) error {
payload := map[string]any{}
if rctx.chatType == chatTypeChannel {
markdown := fmt.Sprintf("[%s]({{tuitui_file %q}})", filename, mediaID)
if isImage {
markdown = fmt.Sprintf("", mediaID)
}
payload["msgtype"] = "richtext/markdown"
payload["richtext"] = map[string]string{
"markdown": markdown,
"delims_left": "{{",
"delims_right": "}}",
}
} else if isImage {View on GitHub (pinned to 4000b2338a)
Solutions
- Set chatType explicitly to the correct constant (chatTypeDirect/chatTypeGroup/chatTypeChannel) when building the replyContext.
- Ensure the chatID uses a format guessChatType can parse (correct prefix) so the fallback guess works.
- Log/print rctx.chatID and rctx.chatType to identify which value is being rejected, then correct it.
- If a new chat type exists upstream, add a case for it in reactToMessage.
Example fix
// before
rctx := replyContext{ChatID: "123"} // chatType empty, guess fails
// after
rctx := replyContext{ChatID: "grp_123", ChatType: chatTypeGroup} Defensive patterns
Strategy: validation
Validate before calling
switch rctx.chatType {
case chatTypeDirect, chatTypeGroup, chatTypeChannel:
// ok
default:
return fmt.Errorf("unsupported chat type %q", rctx.chatType)
} Prevention
- Always set chatType explicitly when constructing replyContext
- Validate chatID prefixes against the documented formats
- Handle guessChatType returning empty as an error early
When it happens
Trigger: Calling reactToMessage with a replyContext whose chatType is not one of the recognized constants (e.g. empty string when guessChatType returned nothing, or a misspelled chat type).
Common situations: Manually constructed replyContext with chatType left unset and a chatID format guessChatType does not recognize; a Tuitui API change introducing a new chat type the adapter doesn't know.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- antigravity: invalid permission behavior %q
- auth.json missing tokens.access_token
- auth.json missing tokens.account_id
- tmux: 'session' option is required (name of the tmux session
- %s must be true or false
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/71587a2add863a2d.
Report an issue: GitHub.