{"record":{"id":"2d79d2ac29fbdc78","repo":"CherryHQ/cherry-studio","slug":"unknown-chat-type-type","errorCode":null,"errorMessage":"Unknown chat type: ${type}","messagePattern":"Unknown chat type: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ai/channels/adapters/qq/QqAdapter.ts","lineNumber":675,"sourceCode":"\n    let endpoint: string\n    const body: Record<string, unknown> = { markdown: { content: text }, msg_type: 2 }\n\n    switch (type) {\n      case 'c2c':\n        endpoint = `${QQ_API_BASE}/v2/users/${id}/messages`\n        break\n      case 'group':\n        endpoint = `${QQ_API_BASE}/v2/groups/${id}/messages`\n        break\n      case 'channel':\n        endpoint = `${QQ_API_BASE}/channels/${id}/messages`\n        break\n      case 'dm':\n        endpoint = `${QQ_API_BASE}/dms/${id}/messages`\n        break\n      default:\n        throw new Error(`Unknown chat type: ${type}`)\n    }\n\n    const seq = replyToMsgId ? this.nextPassiveSeq(chatId, type, replyToMsgId) : undefined\n    if (seq !== undefined) {\n      body.msg_id = replyToMsgId\n      // v2 group/C2C dedupe repeat replies sharing one msg_id; a unique seq keeps every chunk.\n      if (type === 'group' || type === 'c2c') {\n        body.msg_seq = seq\n      }\n    }\n\n    await this.apiRequest(endpoint, { method: 'POST', body })\n  }\n\n  /**\n   * Claim the next passive-reply seq for the exact inbound message being answered, or undefined\n   * to fall back to active push once the reply window has lapsed or the per-msg_id cap (5) is hit.\n   * Advancing the seq keeps chunked replies from being deduped by QQ (same msg_id + msg_seq fails).","sourceCodeStart":657,"sourceCodeEnd":693,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/channels/adapters/qq/QqAdapter.ts#L657-L693","documentation":"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.","triggerScenarios":"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.","commonSituations":"A chatId constructed upstream with a new/unsupported prefix, a malformed chatId (missing ':'), or an inbound message routing to an unknown target type.","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."],"exampleFix":"// before\nconst [type, id] = chatId.split(':')\nlet endpoint: string\nswitch (type) {\n  case 'c2c': ...\n  default: throw new Error(`Unknown chat type: ${type}`)\n}\n\n// after — validate shape up front with a clearer error\nconst m = /^(c2c|group|channel|dm):(.+)$/.exec(chatId)\nif (!m) throw new Error(`Malformed or unsupported chatId: ${chatId}`)\nconst [, type, id] = m","handlingStrategy":"type-guard","validationCode":"// Validate chatId shape before sending.\nconst QQ_CHAT_TYPES = ['c2c', 'group', 'channel', 'dm'] as const\ntype QqChatType = typeof QQ_CHAT_TYPES[number]\nfunction parseQqChatId(chatId: string): { type: QqChatType; id: string } {\n  const m = /^(c2c|group|channel|dm):(.+)$/.exec(chatId)\n  if (!m) throw new Error(`Malformed QQ chatId: ${chatId}`)\n  return { type: m[1] as QqChatType, id: m[2] }\n}","typeGuard":"function isUnknownChatType(e: unknown): e is Error {\n  return e instanceof Error && e.message.startsWith('Unknown chat type:')\n}","tryCatchPattern":"try {\n  await qq.sendToChat(chatId, text)\n} catch (e) {\n  if (isUnknownChatType(e)) { logger.error('Unsupported QQ target', { chatId }); return }\n  throw e\n}","preventionTips":["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."],"tags":["qq","validation","chat-id","routing","type-guard"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}