Skip to content

Conversation

@Kalpana-chavhan
Copy link

@Kalpana-chavhan Kalpana-chavhan commented Jan 3, 2026

Proposed changes

This PR fixes issue #37800 where incoming webhooks failed to process scripts using modern JS syntax (like nullish coalescing ??).

  1. Dependency Fix: Added @babel/plugin-syntax-nullish-coalescing-operator to the server bundle.
  2. UX Improvement: Updated addIncomingIntegration and updateIncomingIntegration to throw a Meteor.Error upon compilation failure. This prevents silent failures and notifies the admin via the UI.

Checklist

  • I have tested these changes locally.
  • I have verified that scripts with ?? now compile and execute.
  • I have verified that invalid scripts now show an error toast in the Admin UI.

Steps to test

  1. Go to Administration -> Integrations -> New Incoming Webhook.
  2. Enable script and use: const x = request.content ?? {};.
  3. Save and verify the integration saves successfully.

closes #37800

Summary by CodeRabbit

  • Bug Fixes

    • Prevent saving broken incoming integrations by failing immediately on script compilation with clearer error messages.
    • Fix channel parsing and resolution so channel identifiers are handled consistently and reliably during integration add/update.
  • Improvements

    • Correct error-context labels to reference the appropriate integration operation (add vs. update).

✏️ Tip: You can customize this high-level summary in your review settings.

@Kalpana-chavhan Kalpana-chavhan requested a review from a team as a code owner January 3, 2026 16:05
@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Jan 3, 2026

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Jan 3, 2026

⚠️ No Changeset found

Latest commit: 8a42091

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 3, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Script compilation now fails fast for incoming integrations (throws Meteor.Error on compile failure) and channel processing was changed to derive and use a non-mutated channelName for all room/user lookups.

Changes

Cohort / File(s) Summary
Add Incoming Integration
apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts
On script compilation failure, throw Meteor.Error('error-invalid-script') immediately (preventing save). Stop mutating channel; derive channelName = channel.slice(1) and use it for room/user DB lookups. Adjust error context method names.
Update Incoming Integration
apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts
Move compilation to pre-update phase, throw Meteor.Error('error-invalid-script') on failure (do not persist compile state on error). Conditionally include scriptCompiled and $unset scriptError only on successful compilation. Stop mutating channel; use channelName for all lookups and update error contexts.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Method as IncomingMethod
  participant Compiler
  participant DB

  Client->>IncomingMethod: call add/updateIncomingIntegration(payload)
  IncomingMethod->>IncomingMethod: validate permissions & params
  IncomingMethod->>Compiler: compile(payload.script)
  alt compilation succeeds
    Compiler-->>IncomingMethod: compiledScript
    IncomingMethod->>DB: insert/update integration (include scriptCompiled, $unset scriptError)
    DB-->>IncomingMethod: ack
    IncomingMethod-->>Client: success (integration saved)
  else compilation fails
    Compiler-->>IncomingMethod: compile error
    IncomingMethod-->>Client: throw Meteor.Error('error-invalid-script') 
    Note right of DB: No persistence of invalid script occurs
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through code to catch a bug,
Compiled each script with a careful tug,
Channels trimmed, names kept neat,
No more saves of broken beet,
Now webhooks dance — oh what a hug!

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: Webhook script compilation failure' directly addresses the main issue fixed—enabling proper error handling and reporting when webhook scripts fail to compile, which is the core objective of this PR.
Linked Issues check ✅ Passed The changes address the primary objectives from #37800: improved error handling when script compilation fails (throwing Meteor.Error instead of failing silently) and surfacing errors to the Admin UI as intended.
Out of Scope Changes check ✅ Passed All modifications in both integration methods (addIncomingIntegration and updateIncomingIntegration) are directly related to fixing script compilation error handling and improving channel processing logic without introducing unrelated changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 3 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts">

<violation number="1" location="apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts:85">
P0: Critical: This code block has been moved outside the function scope to module level. The variables `scriptEngine`, `integrationId`, and `integration` are only defined inside the `updateIncomingIntegration` function. This will cause a `ReferenceError` at module load time and break the entire integration update functionality.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Contributor

@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: 3

🧹 Nitpick comments (2)
apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts (1)

118-127: Consider removing redundant field assignments.

The assignments to integrationData.scriptCompiled and integrationData.scriptError on lines 119-120 are effectively dead code since the Meteor.Error is thrown immediately after, preventing the integration from being saved. The error handling logic correctly surfaces compilation errors to the UI.

🔎 Proposed simplification
 		} catch (e) {
-			integrationData.scriptCompiled = undefined;
-			integrationData.scriptError = e instanceof Error ? _.pick(e, 'name', 'message', 'stack') : undefined;
-
 			// Surfacing the error to the UI to prevent saving a broken integration
 			throw new Meteor.Error(
 				'error-invalid-script',
 				`Compilation Error: ${e instanceof Error ? e.message : 'Unknown error'}`,
 			);
 		}
apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts (1)

85-125: Indentation is inconsistent within the new block.

The code block starting at line 85 (const isFrozen = ...) and the if (!isFrozen) block (lines 87-125) appear to have inconsistent indentation compared to the rest of the function. The function body uses tabs, but this block appears to use different spacing.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d3511ea and 2129237.

📒 Files selected for processing (3)
  • apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts
  • apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts
  • apps/meteor/package.json
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts
  • apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts
🧬 Code graph analysis (1)
apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts (1)
packages/models/src/index.ts (1)
  • Integrations (157-157)

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts">

<violation number="1" location="apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts:183">
P3: Dead code: Since compilation errors throw before reaching this update, `scriptError` will always be falsy here. This spread will always produce an empty object.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Contributor

@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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts (1)

198-201: Wrong method name in error details.

The error references updateOutgoingIntegration but this is the updateIncomingIntegration method.

🔎 Proposed fix
 		if (!this.userId) {
 			throw new Meteor.Error('error-invalid-user', 'Invalid user', {
-				method: 'updateOutgoingIntegration',
+				method: 'updateIncomingIntegration',
 			});
 		}
🧹 Nitpick comments (4)
apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts (1)

128-131: Use slice instead of deprecated substr; consider const for loop variable.

substr is deprecated. Additionally, since channel is no longer reassigned in the loop body, it can be declared as const.

🔎 Proposed fix
-	for await (let channel of channels) {
+	for await (const channel of channels) {
 		let record;
 		const channelType = channel[0];
-		const channelName = channel.substr(1);
+		const channelName = channel.slice(1);
apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts (3)

86-108: Compilation error handling is correct, but lines 99-101 are dead code.

The throw at line 106 ensures the function exits before reaching findOneAndUpdate, which is the correct behavior. However, setting scriptError in the catch block (lines 99-101) serves no purpose since we throw immediately after—the value is never used.

🔎 Proposed simplification
 		} catch (e) {
-			scriptCompiled = undefined;
-			if (e instanceof Error) {
-				const { name, message, stack } = e;
-				scriptError = { name, message, stack };
-			}
-			
-			// We throw the error to notify the UI. Because we are using findOneAndUpdate 
-			// later, the error state is NOT persisted if we throw here, keeping the DB clean.
+			// Throw to notify the UI; DB is not updated since we exit before findOneAndUpdate.
 			throw new Meteor.Error('error-invalid-script', `Compilation Error: ${e instanceof Error ? e.message : 'Unknown error'}`);
 		}

110-112: Consider const for loop variable.

Since channel is no longer reassigned in the loop body, it can be declared as const.

🔎 Proposed fix
-	for await (let channel of channels) {
+	for await (const channel of channels) {
 		const channelType = channel[0];
 		const channelName = channel.slice(1);

181-184: Line 183 is dead code—scriptError is never set when reaching this point.

Since the function throws when compilation fails (line 106), scriptError is always undefined here. The $unset for scriptCompiled based on scriptError will never execute.

🔎 Proposed simplification
 			$unset: {
 				...(scriptCompiled ? { scriptError: 1 as const } : {}),
-				...(scriptError ? { scriptCompiled: 1 as const } : {}),
 			},
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2129237 and a7c5fe1.

📒 Files selected for processing (2)
  • apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts
  • apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts
  • apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts
🧠 Learnings (1)
📚 Learning: 2025-11-10T19:06:20.146Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37408
File: apps/meteor/client/views/admin/ABAC/useRoomAttributeOptions.tsx:53-69
Timestamp: 2025-11-10T19:06:20.146Z
Learning: In the Rocket.Chat repository, do not provide suggestions or recommendations about code sections marked with TODO comments. The maintainers have already identified these as future work and external reviewers lack the full context about implementation plans and timing.

Applied to files:

  • apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: cubic · AI code reviewer
🔇 Additional comments (3)
apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts (2)

119-125: Error handling correctly prevents silent failures.

Throwing on compilation failure ensures the integration is not persisted with an empty scriptCompiled field, which aligns with the PR objective to surface errors to the Admin UI.


133-144: Channel resolution correctly uses derived channelName.

Using channelName for all lookups prevents the previous issue where the loop variable mutation could affect subsequent iterations or lookups.

apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts (1)

166-174: Script state update logic is sound for success path.

The conditional inclusion of scriptCompiled and clearing of scriptError via $unset correctly maintains consistent script state. Note that line 173 (scriptError) is dead code as mentioned above.

@Kalpana-chavhan
Copy link
Author

I have addressed all feedback from @coderabbitai and @cubic-dev-ai:

  • Removed dead code paths involving scriptError after throws.
  • Refactored updateIncomingIntegration to be atomic (removed intermediate DB updates).
  • Fixed the incorrect method name in error details.
  • Replaced deprecated .substr() with .slice().
  • Ensured const is used for loop variables

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 3, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the current state of both modified files to verify the fixes

echo "=== Checking addIncomingIntegration.ts ==="
cat apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts

echo -e "\n\n=== Checking updateIncomingIntegration.ts ==="
cat apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts

Length of output: 12481


@Kalpana-chavhan Thank you for addressing all the feedback! I've verified each fix:

Dead code removal: Both files now throw immediately on compilation failure with no unreachable code paths setting scriptError

Atomic operations: updateIncomingIntegration now compiles scripts before the database update (lines 88-99), with a single findOneAndUpdate call (lines 127-151) that only executes if compilation succeeds

Method name correction: All error objects in updateIncomingIntegration.ts now correctly reference 'updateIncomingIntegration'

Modern syntax: Both files use .slice(1) instead of the deprecated .substr(1) for extracting channel names (line 115 in addIncomingIntegration.ts, line 104 in updateIncomingIntegration.ts)

Loop variables: All for and for await loops consistently use const declarations

The refactored code is clean, atomic, and properly surfaces compilation errors to the Admin UI. Excellent work! 🎉

🐰✨
/) /)
( •᎑• )
( づ♡づ
celebrating clean code!


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

Copy link
Contributor

@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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts (1)

81-83: Unawaited promise causes validation errors to fail silently.

The promise returned by wrapExceptions(...).catch(...) is not awaited. Throwing inside the .catch() callback results in an unhandled rejection rather than an error that stops execution. This directly undermines the PR's goal of surfacing script errors to administrators.

🔎 Proposed fix
-		wrapExceptions(() => validateScriptEngine(scriptEngine)).catch((e) => {
+		await wrapExceptions(() => validateScriptEngine(scriptEngine)).catch((e) => {
 			throw new Meteor.Error(e.message);
 		});
🧹 Nitpick comments (1)
apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts (1)

172-175: Consider clearing scriptError when script is disabled or emptied.

Currently, scriptError is only unset when compilation succeeds (scriptCompiled is truthy). If a user disables the script or clears it entirely, any previous error remains in the database. This isn't necessarily wrong—it preserves error context for debugging—but verify this is the intended behavior.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a7c5fe1 and 8a42091.

📒 Files selected for processing (2)
  • apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts
  • apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts
  • apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
📚 Learning: 2025-11-10T19:06:20.146Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37408
File: apps/meteor/client/views/admin/ABAC/useRoomAttributeOptions.tsx:53-69
Timestamp: 2025-11-10T19:06:20.146Z
Learning: In the Rocket.Chat repository, do not provide suggestions or recommendations about code sections marked with TODO comments. The maintainers have already identified these as future work and external reviewers lack the full context about implementation plans and timing.

Applied to files:

  • apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts
🔇 Additional comments (6)
apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts (3)

70-70: LGTM: Error context corrected.

The method field now correctly references addIncomingIntegration instead of the incorrect updateIncomingIntegration.


117-122: LGTM: Script compilation now fails fast.

The immediate throw on compilation failure prevents saving broken integrations and surfaces errors to the Admin UI, which directly addresses the PR objectives. The error message is descriptive and handles both Error instances and unknown error types safely.


125-141: LGTM: Cleaner channel processing with immutability.

The refactor improves code clarity by:

  • Using const to prevent accidental mutation of the loop variable
  • Deriving channelName explicitly via channel.slice(1)
  • Using the derived channelName consistently for all database lookups

The lookup logic correctly handles both ID-based and name-based channel references (e.g., #roomId vs #roomName, @userId vs @username).

apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts (3)

86-100: Good implementation of fail-fast compilation with proper error surfacing.

The try/catch properly captures Babel compilation errors and throws a Meteor.Error that will propagate to the Admin UI. Exiting before the database update ensures no broken state is persisted. This correctly addresses the original issue.


102-115: Clean channel handling without mutation.

Using const channel and deriving channelName separately improves clarity and avoids the mutation pattern. The lookups correctly use channelName for room/user identification.


147-178: Atomic update structure looks good.

The single findOneAndUpdate with conditional field inclusion addresses previous concerns about partial database updates. Script state is now updated atomically with other integration fields.

@Kalpana-chavhan
Copy link
Author

Hi Maintainers,
Just a gentle follow-up on this PR.
All checks are passing, please let me know if any changes are needed from my side.
Thanks! @KevLehman , @tassoevan , @ricardogarim , @dougfabris

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incoming webhook payload is empty due to script compilation failure

1 participant