fix: tctoken 463/479 — peer guard + retry logic

* feat: apply PR #2339 missing commits (ced3305 + fe5a37c)

Apply two Feb-19 commits from WhiskeySockets/Baileys PR #2339 that
were missing from the initial integration:

ced3305 — Prevent tctoken attachment to peer (AppStateSync) messages
- Add isPeerMessage guard: additionalAttributes?.['category'] === 'peer'
- Exclude peer messages from is1on1Send to fix error 479 (SmaxInvalid)
  which was causing hundreds of rejections on multi-device sync JIDs

fe5a37c — Error 463 retry logic + blocking→non-blocking refactor
- Replace blocking await getPrivacyTokens() with fire-and-forget .then/.catch
  so the send path is never delayed by a token fetch
- Add tcTokenRetriedMsgIds Set in messages-recv.ts to track retried msgIds
- On error 463 (MissingTcToken): wait 1.5s then relay the message once,
  allowing the server's tctoken notification to arrive before resend
- Add retry_463_ok log event to baileys-logger for observability
This commit is contained in:
Renato Alcara
2026-02-20 00:39:21 -03:00
committed by GitHub
parent 37e9a1ef39
commit 33cce2a6c2
3 changed files with 84 additions and 65 deletions
+32 -1
View File
@@ -155,6 +155,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
const TC_TOKEN_INDEX_KEY = '__index'
const TC_TOKEN_PRUNE_TS_KEY = '__prune_ts'
const tcTokenKnownJids = new Set<string>()
const tcTokenRetriedMsgIds = new Set<string>()
let tcTokenIndexSaveTimer: ReturnType<typeof setTimeout> | undefined
let lastTcTokenPruneTs = 0
@@ -1876,7 +1877,37 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
// device could not display the message
if(attrs.error) {
if(attrs.error === SERVER_ERROR_CODES.MissingTcToken) {
logTcToken('error_463', { jid: attrs.from, msgId: attrs.id })
const msgId = attrs.id
const jid = attrs.from
logTcToken('error_463', { jid, msgId })
// Single-retry: wait 1.5s for the server's tctoken notification to arrive,
// then resend. A Set prevents infinite retry loops.
if(msgId && jid && !tcTokenRetriedMsgIds.has(msgId)) {
tcTokenRetriedMsgIds.add(msgId)
// Safety cap — prevent unbounded memory growth
if(tcTokenRetriedMsgIds.size > 500) {
tcTokenRetriedMsgIds.clear()
}
;(async () => {
try {
await delay(1500)
const msg = await getMessage(key)
if(msg) {
await relayMessage(jid, msg, { messageId: msgId, useUserDevicesCache: true })
logTcToken('retry_463_ok', { jid, msgId })
} else {
logger.warn({ jid, msgId }, '463 retry: message not found in store')
ev.emit('messages.update', [{ key, update: { status: WAMessageStatus.ERROR, messageStubParameters: ['463'] } }])
}
} catch(err: any) {
logger.warn({ jid, msgId, err: err?.message }, '463 retry failed')
ev.emit('messages.update', [{ key, update: { status: WAMessageStatus.ERROR, messageStubParameters: ['463'] } }])
}
})()
return
}
} else if(attrs.error === SERVER_ERROR_CODES.SmaxInvalid) {
logTcToken('error_479', { jid: attrs.from, msgId: attrs.id })
} else {