Skip to content

Implement two-stage protocol fallback in fetchProps for chat requests' or 'Add legacy protocol-1 fallback to fetchProps for compatibility#2478

Open
ojuolokun86 wants to merge 3 commits intoWhiskeySockets:masterfrom
ojuolokun86:dev-bot
Open

Implement two-stage protocol fallback in fetchProps for chat requests' or 'Add legacy protocol-1 fallback to fetchProps for compatibility#2478
ojuolokun86 wants to merge 3 commits intoWhiskeySockets:masterfrom
ojuolokun86:dev-bot

Conversation

@ojuolokun86
Copy link
Copy Markdown

@ojuolokun86 ojuolokun86 commented Apr 10, 2026

Summary by CodeRabbit

  • Bug Fixes

    • More robust property retrieval with an explicit two-step fallback, clearer warnings, and safe return of empty properties on repeated failure.
  • Improvements

    • Better credential hash handling and conditional state updates to keep auth state more consistent; additional success logging when props are fetched.
  • Chores

    • package-lock.json is now ignored via .gitignore.

@whiskeysockets-bot
Copy link
Copy Markdown
Contributor

whiskeysockets-bot commented Apr 10, 2026

Thanks for opening this pull request and contributing to the project!

The next step is for the maintainers to review your changes. If everything looks good, it will be approved and merged into the main branch.

In the meantime, anyone in the community is encouraged to test this pull request and provide feedback.

✅ How to confirm it works

If you’ve tested this PR, please comment below with:

Tested and working ✅

This helps us speed up the review and merge process.

📦 To test this PR locally:

# NPM
npm install @whiskeysockets/baileys@ojuolokun86/Baileys#dev-bot

# Yarn (v2+)
yarn add @whiskeysockets/baileys@ojuolokun86/Baileys#dev-bot

# PNPM
pnpm add @whiskeysockets/baileys@ojuolokun86/Baileys#dev-bot

If you encounter any issues or have feedback, feel free to comment as well.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 10, 2026

📝 Walkthrough

Walkthrough

fetchProps was rewritten to try protocol-2 (xmlns: 'abt') first, then fallback to protocol-1 (xmlns: 'w') on failure; it enforces non-empty props, updates/stores lastPropHash and emits creds.update when a hash exists, logs warnings, and returns {} if both attempts fail.

Changes

Cohort / File(s) Summary
Two-Stage Protocol Fallback
src/Socket/chats.ts
Refactored fetchProps into an explicit two-step flow: attempt protocol-2 (xmlns: 'abt', protocol: '2') then fallback to protocol-1 (xmlns: 'w', protocol: '1') on error; require non-empty props, reduce props node to a dictionary, update authState.creds.lastPropHash and emit creds.update only when a hash attribute is present, log warnings, log fetched props on final success, and return {} if both attempts fail.
Ignore Lockfile
.gitignore
Added package-lock.json to .gitignore.

Sequence Diagram

sequenceDiagram
    participant Caller as Caller
    participant FP as fetchProps()
    participant P2 as Protocol-2 (xmlns: 'abt')
    participant P1 as Protocol-1 (xmlns: 'w')
    participant Creds as Credentials Storage
    participant Evt as Event Emitter
    participant Logger as Logger

    Caller->>FP: call fetchProps()
    FP->>P2: send IQ props request (protocol: '2')
    alt Protocol-2 returns valid props
        P2-->>FP: props node
        FP->>FP: reduce props -> dict
        FP->>Creds: update lastPropHash (if present)
        FP->>Evt: emit creds.update (if hash present)
        FP->>Logger: log "fetched props"
        FP-->>Caller: return props
    else Protocol-2 fails or empty props
        P2-->>FP: error or missing/empty props
        FP->>Logger: warn about protocol-2 failure
        FP->>P1: send IQ props request (protocol: '1', maybe lastPropHash)
        alt Protocol-1 returns valid props
            P1-->>FP: props node
            FP->>FP: reduce props -> dict
            FP->>Creds: update lastPropHash (if present)
            FP->>Evt: emit creds.update (if hash present)
            FP->>Logger: log "fetched props"
            FP-->>Caller: return props
        else Protocol-1 fails or empty props
            P1-->>FP: error or missing/empty props
            FP->>Logger: warn about protocol-1 failure
            FP-->>Caller: return {}
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I bounced to the new tunnel, peered into the old,
Collected tiny props and a hash to hold,
If the shiny path falters, I kindly reboot,
I stash the hash, I send the toot—
Two hops, one breakfast, resilient and bold! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title is partially related to the changeset. It mentions implementing a two-stage protocol fallback in fetchProps, which aligns with the refactoring described in the summary. However, the title is overly broad and does not clearly emphasize that this is specifically a fix for ABT protocol 2 props handling when props are missing or empty, which is the core issue being addressed.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/Socket/chats.ts (1)

882-885: Emit only the changed credential fields.

creds.update is used as a partial-update event everywhere else in this file. Sending the full authState.creds object here leaks a live mutable reference across the event bus for a single-field change and makes downstream persistence do more work than necessary.

Suggested fix
-						authState.creds.lastPropHash = propsNode2.attrs.hash;
-						ev.emit('creds.update', authState.creds);
+						authState.creds.lastPropHash = propsNode2.attrs.hash;
+						ev.emit('creds.update', { lastPropHash: propsNode2.attrs.hash });
-						authState.creds.lastPropHash = propsNode1.attrs.hash;
-						ev.emit('creds.update', authState.creds);
+						authState.creds.lastPropHash = propsNode1.attrs.hash;
+						ev.emit('creds.update', { lastPropHash: propsNode1.attrs.hash });

Also applies to: 918-921

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Socket/chats.ts` around lines 882 - 885, The emit currently sends the
full mutable authState.creds object; change the ev.emit('creds.update',
authState.creds) calls to emit only the changed fields as a partial object
(e.g., after setting authState.creds.lastPropHash = propsNode2.attrs.hash, call
ev.emit('creds.update', { lastPropHash: propsNode2.attrs.hash })); apply the
same pattern to the other similar emit (the one that updates a single creds
field around the later block) so callers receive only the changed key(s) and we
avoid leaking a live creds reference.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Socket/chats.ts`:
- Around line 879-888: If the ABT protocol call (query()) succeeds but
getBinaryNodeChild(resultNode2, 'props') is missing or
reduceBinaryNodeToDictionary(propsNode2, 'prop') yields an empty object, fall
back to the legacy protocol:'1' path instead of returning an empty result;
update the logic around propsNode2 handling in the function that calls query()
so that after calling getBinaryNodeChild you check for both a missing propsNode2
and an empty props object, only set authState.creds.lastPropHash and emit
creds.update when propsNode2.attrs.hash exists, and invoke the existing legacy
code path (the same code used when query() throws) when props are absent/empty
to ensure the fallback path runs.

---

Nitpick comments:
In `@src/Socket/chats.ts`:
- Around line 882-885: The emit currently sends the full mutable authState.creds
object; change the ev.emit('creds.update', authState.creds) calls to emit only
the changed fields as a partial object (e.g., after setting
authState.creds.lastPropHash = propsNode2.attrs.hash, call
ev.emit('creds.update', { lastPropHash: propsNode2.attrs.hash })); apply the
same pattern to the other similar emit (the one that updates a single creds
field around the later block) so callers receive only the changed key(s) and we
avoid leaking a live creds reference.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 24feedf8-a3f5-41e0-bdae-c7e979ab4f9a

📥 Commits

Reviewing files that changed from the base of the PR and between 8e5093c and 25c947b.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (1)
  • src/Socket/chats.ts

Comment thread src/Socket/chats.ts Outdated
@ojuolokun86 ojuolokun86 changed the title Fix chat 405 bad request issue in bailey Implement two-stage protocol fallback in fetchProps for chat requests' or 'Add legacy protocol-1 fallback to fetchProps for compatibility Apr 10, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Socket/chats.ts`:
- Around line 951-954: The current fallback hides the legacy (protocol-1) error
because logger.warn doesn't include error objects and the code rethrows
firstError instead of preserving both failures; update the block around the
protocol fallback handling (references: variables firstError and err1 and the
logger.warn call) to log both errors (e.g., logger.error or logger.warn
including err1 and firstError) and throw an aggregated error that preserves both
failures (e.g., create a new Error whose message includes both err1 and
firstError details or attach one as the cause/property) so callers can see full
failure context.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 882807d3-9bf1-4490-b541-9b8f3f08605b

📥 Commits

Reviewing files that changed from the base of the PR and between 25c947b and e96d3c8.

📒 Files selected for processing (2)
  • .gitignore
  • src/Socket/chats.ts
✅ Files skipped from review due to trivial changes (1)
  • .gitignore

Comment thread src/Socket/chats.ts Outdated
Comment on lines +951 to +954
logger.warn('⚠️ both protocol 1 and 2 failed');

// 🔥 IMPORTANT: throw real error instead of silent {}
throw firstError || err1;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Don't lose the protocol-1 failure details.

Line 954 will always rethrow the outer firstError, and Line 951 logs no error objects. If both requests fail, the actual legacy failure is hidden, which makes this fallback hard to debug.

Suggested change
-		} catch (err1) {
-			logger.warn('⚠️ both protocol 1 and 2 failed');
-
-			// 🔥 IMPORTANT: throw real error instead of silent {}
-			throw firstError || err1;
+		} catch (err1) {
+			logger.warn({ protocol2Error: firstError, protocol1Error: err1 }, 'both protocol 1 and 2 failed');
+			throw err1;
 		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
logger.warn('⚠️ both protocol 1 and 2 failed');
// 🔥 IMPORTANT: throw real error instead of silent {}
throw firstError || err1;
logger.warn({ protocol2Error: firstError, protocol1Error: err1 }, 'both protocol 1 and 2 failed');
throw err1;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Socket/chats.ts` around lines 951 - 954, The current fallback hides the
legacy (protocol-1) error because logger.warn doesn't include error objects and
the code rethrows firstError instead of preserving both failures; update the
block around the protocol fallback handling (references: variables firstError
and err1 and the logger.warn call) to log both errors (e.g., logger.error or
logger.warn including err1 and firstError) and throw an aggregated error that
preserves both failures (e.g., create a new Error whose message includes both
err1 and firstError details or attach one as the cause/property) so callers can
see full failure context.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
src/Socket/chats.ts (1)

907-908: ⚠️ Potential issue | 🟡 Minor

Include both caught errors in logs before returning {}.

Line 907 and Line 951 currently log generic warnings without error objects, which makes protocol fallback failures hard to diagnose.

Suggested logging fix
-		logger.warn('⚠️ protocol 2 failed or invalid, trying protocol 1');
+		logger.warn({ protocol2Error: err2 }, 'protocol 2 failed or invalid, trying protocol 1');

...
-			logger.warn('⚠️ both protocol 1 and 2 failed');
+			logger.warn({ protocol2Error: firstError, protocol1Error: err1 }, 'both protocol 1 and 2 failed');
 			return {};

Also applies to: 951-954

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Socket/chats.ts` around lines 907 - 908, The current fallback logic logs
only generic warnings (logger.warn('⚠️ protocol 2 failed or invalid, trying
protocol 1') and the similar message at the second fallback) and then returns {}
without logging the caught error objects; update the catch blocks around the
protocol parsing code (the places that call logger.warn for "protocol 2 failed"
and the later fallback) to include the caught Error objects in the log (e.g.,
logger.warn('⚠️ protocol 2 failed or invalid, trying protocol 1', err) and
similarly for the protocol 1 fallback) so both exceptions are recorded before
returning {}.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/Socket/chats.ts`:
- Around line 907-908: The current fallback logic logs only generic warnings
(logger.warn('⚠️ protocol 2 failed or invalid, trying protocol 1') and the
similar message at the second fallback) and then returns {} without logging the
caught error objects; update the catch blocks around the protocol parsing code
(the places that call logger.warn for "protocol 2 failed" and the later
fallback) to include the caught Error objects in the log (e.g., logger.warn('⚠️
protocol 2 failed or invalid, trying protocol 1', err) and similarly for the
protocol 1 fallback) so both exceptions are recorded before returning {}.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2f2f889b-5528-4574-889b-9540b901a5bb

📥 Commits

Reviewing files that changed from the base of the PR and between e96d3c8 and ac26650.

📒 Files selected for processing (1)
  • src/Socket/chats.ts

@github-actions
Copy link
Copy Markdown
Contributor

This PR is stale because it has been open for 14 days with no activity. Remove the stale label or comment or this will be closed in 14 days

@github-actions github-actions Bot added the Stale label Apr 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

2 participants