Skip to content

Commit 262c930

Browse files
CyPackclaude
authored andcommitted
fix(media): correct mediaKey Uint8Array conversion from PostgreSQL JSONB
PostgreSQL JSONB stores object keys lexicographically, so a Uint8Array serialized as {0:b0,1:b1,...,9:b9,10:b10,...} is retrieved with keys in order "0","1","10","11",...,"19","2","20",...,"9". Using Object.values() on this gives bytes in the WRONG order, causing Baileys HKDF/AES-GCM to fail with "Unsupported state or unable to authenticate data". Fix: sort keys numerically before constructing Uint8Array, and also handle base64-encoded string mediaKey (from HTTP request bodies). This matches OwnPilot retryMediaFromMetadata() which uses: new Uint8Array(Buffer.from(base64mediaKey, 'base64')) Before: updateMediaMessage → "Unsupported state or unable to authenticate data" After: updateMediaMessage → re-upload → fresh CDN URL → download ✅ Tested: 2312ZL_2_A_V1.SOR (expired CDN, fromMe=true) → 21058 bytes ✅ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent f268571 commit 262c930

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3889,8 +3889,21 @@ export class BaileysStartupService extends ChannelStartupService {
38893889
}
38903890
}
38913891

3892-
if (typeof mediaMessage['mediaKey'] === 'object') {
3893-
msg.message[mediaType].mediaKey = Uint8Array.from(Object.values(mediaMessage['mediaKey']));
3892+
if (typeof mediaMessage['mediaKey'] === 'string') {
3893+
// base64-encoded string (e.g. from HTTP request body) → Uint8Array
3894+
// This matches OwnPilot retryMediaFromMetadata: new Uint8Array(Buffer.from(base64, 'base64'))
3895+
msg.message[mediaType].mediaKey = new Uint8Array(Buffer.from(mediaMessage['mediaKey'], 'base64'));
3896+
} else if (
3897+
typeof mediaMessage['mediaKey'] === 'object' &&
3898+
!Buffer.isBuffer(mediaMessage['mediaKey']) &&
3899+
!(mediaMessage['mediaKey'] instanceof Uint8Array)
3900+
) {
3901+
// Plain object {0:b0, 1:b1, ...} from PostgreSQL JSONB deserialization.
3902+
// CRITICAL: JSONB stores keys lexicographically ("0","1","10","11",...,"2",...,"9")
3903+
// so Object.values() gives WRONG byte order. Must sort keys numerically first.
3904+
const keyObj = mediaMessage['mediaKey'] as Record<string, number>;
3905+
const sortedKeys = Object.keys(keyObj).sort((a, b) => parseInt(a, 10) - parseInt(b, 10));
3906+
msg.message[mediaType].mediaKey = new Uint8Array(sortedKeys.map((k) => keyObj[k]));
38943907
}
38953908

38963909
let buffer: Buffer;

0 commit comments

Comments
 (0)