fix(messages-recv): plain ack and error handling on early-ignore path

Addresses Codex P1 + Copilot + CodeRabbit review on PR #383:

1. Use plain sendMessageAck(node) for ignored messages — InfiniteAPI's
   prior in-handler check did NOT use NACK_REASONS.UnhandledError. The
   error code reports a processing failure and can trigger server-side
   retries; ignored stanzas are an intentional drop, not a failure.
   Restoring the original semantics.

2. Wrap the early-ignore block in try/catch routing to onUnexpectedError.
   shouldIgnoreJid is a user-provided callback and sendMessageAck can
   throw (e.g. websocket closed). Without this guard, the error becomes
   an unhandled promise rejection because the early path runs outside
   processNodeWithBuffer's catch wrapper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Renato Alcara
2026-04-25 13:08:54 -03:00
parent fa7cc63846
commit c46889db43
+25 -13
View File
@@ -3091,21 +3091,33 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
// Fast path: ack and drop ignored JIDs before entering the buffer/queue. // Fast path: ack and drop ignored JIDs before entering the buffer/queue.
// Skips type='call' so call events are never silently dropped via // Skips type='call' so call events are never silently dropped via
// shouldIgnoreJid (preserves InfiniteAPI's pre-existing behavior). // shouldIgnoreJid (preserves InfiniteAPI's pre-existing behavior).
// Wrapped in try/catch so a throw from shouldIgnoreJid (user callback)
// or sendMessageAck (e.g. websocket closed) is routed through
// onUnexpectedError instead of becoming an unhandled rejection —
// matches the protection processNodeWithBuffer provides.
if (type !== 'call') { if (type !== 'call') {
const from = node.attrs.from try {
let ignoreJid = from const from = node.attrs.from
if (type === 'receipt' && from) { let ignoreJid = from
const attrs = node.attrs if (type === 'receipt' && from) {
const isLid = attrs.from!.includes('lid') const attrs = node.attrs
const isNodeFromMe = areJidsSameUser( const isLid = attrs.from!.includes('lid')
attrs.participant || attrs.from, const isNodeFromMe = areJidsSameUser(
isLid ? authState.creds.me?.lid : authState.creds.me?.id attrs.participant || attrs.from,
) isLid ? authState.creds.me?.lid : authState.creds.me?.id
ignoreJid = !isNodeFromMe || isJidGroup(attrs.from) ? attrs.from : attrs.recipient )
} ignoreJid = !isNodeFromMe || isJidGroup(attrs.from) ? attrs.from : attrs.recipient
}
if (ignoreJid && ignoreJid !== S_WHATSAPP_NET && shouldIgnoreJid(ignoreJid)) { if (ignoreJid && ignoreJid !== S_WHATSAPP_NET && shouldIgnoreJid(ignoreJid)) {
await sendMessageAck(node, type === 'message' ? NACK_REASONS.UnhandledError : undefined) // Plain ack (no NACK error code) preserves InfiniteAPI's prior
// behavior — ignored stanzas are an intentional drop, not a
// processing failure, so we don't want server-side retries.
await sendMessageAck(node)
return
}
} catch (error) {
onUnexpectedError(error as Error, identifier)
return return
} }
} }