Skip to content

fix(whatsapp): harden Baileys media upload hotfix#65966

Merged
frankekn merged 15 commits into
mainfrom
fix/whatsapp-baileys-media-upload-generic-agent
Apr 14, 2026
Merged

fix(whatsapp): harden Baileys media upload hotfix#65966
frankekn merged 15 commits into
mainfrom
fix/whatsapp-baileys-media-upload-generic-agent

Conversation

@frankekn

Copy link
Copy Markdown
Contributor

What changed

This PR adds a Baileys dependency patch for WhatsApp media sends.

  • wait for encryptedStream() output streams to finish before returning the encrypted temp file path
  • make the Baileys media upload path compatible with generic fetchAgent objects that do not implement Undici's Dispatcher interface
  • read the encrypted payload into a buffer before upload instead of relying on a fresh read stream from a just-written temp file

Why

We hit two separate failures while sending XLSX documents over WhatsApp:

  1. encryptedStream() could return before the encrypted temp file was fully flushed to disk, which led to ENOENT races on /tmp/document*-enc
  2. even after fixing the temp-file race, uploads still failed before any host response because the upload path passed a generic Node Agent via dispatcher, which caused TypeError: agent.dispatch is not a function

Together, these failures broke WhatsApp document sends and could take the gateway into repeated recovery / retry failure paths.

Impact

  • WhatsApp document sends no longer race on temp-file creation
  • WhatsApp media upload works in environments where Baileys receives a generic fetchAgent
  • the fix is carried in the repo's patched dependency flow, instead of staying as an untracked runtime hotfix

Validation

  • reproduced the failure locally against the live gateway
  • confirmed the pre-fix temp-file race with runtime instrumentation
  • confirmed the post-race failure cause was agent.dispatch is not a function
  • applied the same logic in the local runtime and verified XLSX upload succeeded with a 200 OK media upload response and successful WhatsApp send
  • verified the repository patch applies cleanly against @whiskeysockets/baileys@7.0.0-rc.9 via patch --dry-run

@openclaw-barnacle openclaw-barnacle Bot added size: S maintainer Maintainer-authored PR labels Apr 13, 2026
@frankekn

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6e065b660

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

let result;
try {
- const stream = createReadStream(filePath);
+ const body = await fs.readFile(filePath);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep media upload streaming instead of full-buffer reads

Replacing createReadStream(filePath) with await fs.readFile(filePath) forces every media upload to hold the entire encrypted payload in memory before the request is sent. For large WhatsApp documents/videos (or multiple concurrent sends), this can spike RSS by payload size per upload and trigger OOM/restarts in production, which is a regression from the previous streaming behavior.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6e065b660

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +27 to +33
- const stream = createReadStream(filePath);
+ const body = await fs.readFile(filePath);
const response = await fetch(url, {
- dispatcher: fetchAgent,
method: 'POST',
- body: stream,
+ body,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep media uploads streaming instead of buffering whole file

Replacing createReadStream(filePath) with await fs.readFile(filePath) forces every encrypted media upload to be fully materialized in memory before POSTing. For large WhatsApp documents/videos (and especially concurrent sends), this can create major RSS spikes, trigger GC/OOM failures, and drop uploads that previously worked with bounded memory via streaming; this is a runtime regression in the hot upload path rather than a cosmetic refactor.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@openclaw-barnacle openclaw-barnacle Bot added size: S channel: whatsapp-web Channel integration: whatsapp-web scripts Repository scripts size: M and removed size: XS size: S labels Apr 14, 2026
@frankekn frankekn force-pushed the fix/whatsapp-baileys-media-upload-generic-agent branch from 39c45e9 to e13bdc5 Compare April 14, 2026 05:09
@frankekn

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e13bdc5759

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +409 to +413
const transitiveClosure = collectInstalledRuntimeClosure(rootNodeModulesDir, dependencySpecs);
if (transitiveClosure !== null) {
for (const depName of transitiveClosure) {
dependencyNames.add(depName);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fall back to install when transitive closure lookup fails

When collectInstalledRuntimeClosure() returns null, this code now keeps staging with only direct dependencies instead of aborting root staging. That can produce incomplete dist/extensions/*/node_modules trees whenever a transitive package is missing/incompatible at the root (for example platform-optional transitives), because hoisted layouts often keep required transitives outside the direct package folder; copying only the direct package then leads to runtime MODULE_NOT_FOUND failures. The previous behavior (return false) correctly fell back to npm install for a complete closure.

Useful? React with 👍 / 👎.

@frankekn

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b35564b436

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +50 to +52
"bundle": {
"stageRuntimeDependencies": true
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Remove duplicated openclaw.bundle key

This adds a second openclaw.bundle object even though the same key already exists later in the same openclaw object. Duplicate keys in JSON are ambiguous (many parsers keep only the last occurrence), so a future edit to one block can be silently ignored and cause confusing staging behavior drift. Keep a single canonical bundle entry.

Useful? React with 👍 / 👎.

@frankekn

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0a5ef08334

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread package.json
Comment on lines +1523 to +1524
"patchedDependencies": {
"@whiskeysockets/baileys@7.0.0-rc.9": "patches/@whiskeysockets__baileys@7.0.0-rc.9.patch"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Ship Baileys dispatcher fix beyond pnpm-only patching

This change delivers the WhatsApp upload fix only through pnpm.patchedDependencies, but the shipped install path still installs bundled plugin deps with npm install (scripts/postinstall-bundled-plugins.mjs:423-438), where the only runtime rewrite is the encrypted-stream flush hotfix (scripts/postinstall-bundled-plugins.mjs:41-57). That means npm/global installs can still run unpatched Baileys upload code and hit TypeError: agent.dispatch is not a function with non-Undici agents, so the dispatcher hardening in this commit is not actually applied in that environment.

Useful? React with 👍 / 👎.

@frankekn

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 133cc52081

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/postinstall-bundled-plugins.mjs Outdated
Comment on lines +273 to +275
if (!patchedText.includes(BAILEYS_MEDIA_HOTFIX_REPLACEMENT)) {
if (!patchedText.includes(BAILEYS_MEDIA_HOTFIX_NEEDLE)) {
return { applied: false, reason: "unexpected_content" };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Handle patched encrypted-stream variant before bailing out

The hotfix matcher now assumes only one “already patched” form (await Promise.all(...)), but this same commit adds a pnpm patch that uses the equivalent sequential awaits (await encFinishPromise; await originalFinishPromise;). In that valid patched state, this branch returns unexpected_content immediately, which causes source-checkout postinstall runs to warn on every install and prevents dispatcher-only patching for that file variant. Please accept the sequential-await form as patched (or continue to the dispatcher patch path) instead of returning early.

Useful? React with 👍 / 👎.

@frankekn

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d5b9ff0150

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/postinstall-bundled-plugins.mjs Outdated
Comment on lines +285 to +289
patchedText.includes(BAILEYS_MEDIA_HOTFIX_REPLACEMENT) ||
patchedText.includes(BAILEYS_MEDIA_HOTFIX_SEQUENTIAL_REPLACEMENT);

if (!encryptedStreamAlreadyPatched) {
if (!patchedText.includes(BAILEYS_MEDIA_HOTFIX_NEEDLE)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Treat commented sequential Baileys patch as already applied

This detection path relies on an exact multiline match for the sequential encrypted-stream replacement, then falls back to requiring the old unpatched needle. The new pnpm patch in this commit adds comment lines between those statements, so a file that is already patched via patches/@whiskeysockets__baileys@7.0.0-rc.9.patch does not match either form and returns unexpected_content. In source-checkout postinstall runs, that makes the hotfix non-idempotent (spurious warning every install) and can skip dispatcher backfill in mixed states where only the commented sequential variant is present.

Useful? React with 👍 / 👎.

@frankekn

Copy link
Copy Markdown
Contributor Author

@codex review

@frankekn

Copy link
Copy Markdown
Contributor Author

@codex review

@frankekn frankekn force-pushed the fix/whatsapp-baileys-media-upload-generic-agent branch from 04932d0 to b5db59b Compare April 14, 2026 13:33
@frankekn frankekn merged commit d86527d into main Apr 14, 2026
27 checks passed
@frankekn frankekn deleted the fix/whatsapp-baileys-media-upload-generic-agent branch April 14, 2026 13:34
@frankekn

Copy link
Copy Markdown
Contributor Author

Merged via squash.

Thanks @frankekn!

steipete pushed a commit that referenced this pull request Apr 14, 2026
Merged via squash.

Prepared head SHA: b5db59b
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
kvnkho pushed a commit to kvnkho/openclaw that referenced this pull request Apr 17, 2026
Merged via squash.

Prepared head SHA: b5db59b
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
Merged via squash.

Prepared head SHA: b5db59b
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
Merged via squash.

Prepared head SHA: b5db59b
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
Merged via squash.

Prepared head SHA: b5db59b
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
globalcaos pushed a commit to globalcaos/tinkerclaw that referenced this pull request May 13, 2026
Merged via squash.

Prepared head SHA: b5db59b
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
Merged via squash.

Prepared head SHA: b5db59b
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
Merged via squash.

Prepared head SHA: b5db59b
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: whatsapp-web Channel integration: whatsapp-web maintainer Maintainer-authored PR scripts Repository scripts size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant