diff --git a/lib/Utils/messages-media.js b/lib/Utils/messages-media.js index 0d32dfb4882dfe029ba8804772d7d89404b08e76..73809fcd1d52362aef0c35cb7416c29d86482df0 100644 --- a/lib/Utils/messages-media.js +++ b/lib/Utils/messages-media.js @@ -353,9 +353,17 @@ const fileSha256 = sha256Plain.digest(); const fileEncSha256 = sha256Enc.digest(); encFileWriteStream.write(mac); + // Create finish promises before calling end() to avoid missing the event + const encFinishPromise = once(encFileWriteStream, 'finish'); + const originalFinishPromise = originalFileStream ? once(originalFileStream, 'finish') : Promise.resolve(); encFileWriteStream.end(); originalFileStream?.end?.(); stream.destroy(); + // Wait for write streams to fully flush to disk before returning encFilePath. + // Without this await, the caller may open a read stream on the file before + // the OS has created it, causing a race-condition ENOENT crash. + await encFinishPromise; + await originalFinishPromise; logger?.debug('encrypted data successfully'); return { mediaKey, @@ -520,11 +528,10 @@ // eslint-disable-next-line @typescript-eslint/no-explicit-any let result; try { const stream = createReadStream(filePath); const response = await fetch(url, { - dispatcher: fetchAgent, method: 'POST', body: stream, headers: { ...(() => { const hdrs = options?.headers; @@ -535,6 +542,11 @@ 'Content-Type': 'application/octet-stream', Origin: DEFAULT_ORIGIN }, + // Baileys passes a generic agent here in some runtimes. Undici's + // `dispatcher` only works with Dispatcher-compatible implementations, + // so only wire it through when the object actually implements + // `dispatch`. + ...(typeof fetchAgent?.dispatch === 'function' ? { dispatcher: fetchAgent } : {}), duplex: 'half', // Note: custom agents/proxy require undici Agent; omitted here. signal: timeoutMs ? AbortSignal.timeout(timeoutMs) : undefined