CherryHQ/cherry-studio · error · Error
Unknown chat type: ${type}
Error message
Unknown chat type: ${type} What it means
Thrown by QqAdapter.sendToChat() when the prefix of chatId (the part before ':') is not one of the handled cases (c2c, group, channel, dm). chatId is parsed via chatId.split(':') and the type half is switched on; an unrecognized type hits default.
Source
Thrown at src/main/ai/channels/adapters/qq/QqAdapter.ts:675
let endpoint: string
const body: Record<string, unknown> = { markdown: { content: text }, msg_type: 2 }
switch (type) {
case 'c2c':
endpoint = `${QQ_API_BASE}/v2/users/${id}/messages`
break
case 'group':
endpoint = `${QQ_API_BASE}/v2/groups/${id}/messages`
break
case 'channel':
endpoint = `${QQ_API_BASE}/channels/${id}/messages`
break
case 'dm':
endpoint = `${QQ_API_BASE}/dms/${id}/messages`
break
default:
throw new Error(`Unknown chat type: ${type}`)
}
const seq = replyToMsgId ? this.nextPassiveSeq(chatId, type, replyToMsgId) : undefined
if (seq !== undefined) {
body.msg_id = replyToMsgId
// v2 group/C2C dedupe repeat replies sharing one msg_id; a unique seq keeps every chunk.
if (type === 'group' || type === 'c2c') {
body.msg_seq = seq
}
}
await this.apiRequest(endpoint, { method: 'POST', body })
}
/**
* Claim the next passive-reply seq for the exact inbound message being answered, or undefined
* to fall back to active push once the reply window has lapsed or the per-msg_id cap (5) is hit.
* Advancing the seq keeps chunked replies from being deduped by QQ (same msg_id + msg_seq fails).View on GitHub (pinned to 726446b54c)
Solutions
- Normalize all chatIds at ingestion to one of the four supported prefixes; reject others before they reach sendToChat.
- Validate chatId with a regex like /^(c2c|group|channel|dm):/ before sending.
- Add the new type as an explicit case if QQ introduces one, mapping it to the correct API path.
Example fix
// before
const [type, id] = chatId.split(':')
let endpoint: string
switch (type) {
case 'c2c': ...
default: throw new Error(`Unknown chat type: ${type}`)
}
// after — validate shape up front with a clearer error
const m = /^(c2c|group|channel|dm):(.+)$/.exec(chatId)
if (!m) throw new Error(`Malformed or unsupported chatId: ${chatId}`)
const [, type, id] = m Defensive patterns
Strategy: type-guard
Validate before calling
// Validate chatId shape before sending.
const QQ_CHAT_TYPES = ['c2c', 'group', 'channel', 'dm'] as const
type QqChatType = typeof QQ_CHAT_TYPES[number]
function parseQqChatId(chatId: string): { type: QqChatType; id: string } {
const m = /^(c2c|group|channel|dm):(.+)$/.exec(chatId)
if (!m) throw new Error(`Malformed QQ chatId: ${chatId}`)
return { type: m[1] as QqChatType, id: m[2] }
} Type guard
function isUnknownChatType(e: unknown): e is Error {
return e instanceof Error && e.message.startsWith('Unknown chat type:')
} Try / catch
try {
await qq.sendToChat(chatId, text)
} catch (e) {
if (isUnknownChatType(e)) { logger.error('Unsupported QQ target', { chatId }); return }
throw e
} Prevention
- Normalize all chatIds at ingestion to one of the four supported prefixes.
- Validate chatId with a regex before sending.
- Add explicit switch cases for any new QQ chat type.
When it happens
Trigger: sendToChat(chatId, text, replyToMsgId) receives a chatId whose first segment is anything other than 'c2c','group','channel','dm' — e.g. an empty string, a typo, a chatId with no colon, or a future chat type not yet supported.
Common situations: A chatId constructed upstream with a new/unsupported prefix, a malformed chatId (missing ':'), or an inbound message routing to an unknown target type.
Related errors
- QQ Bot AppID and ClientSecret are required
- Invalid token response from QQ API: ${errorText}
- Invalid arguments for brave_web_search
- Invalid arguments for brave_local_search
- MethodNotFound
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/2d79d2ac29fbdc78.
Report an issue: GitHub.