Skip to content

fix: findIndex missing return, isURL null guard, sanitizeString null guard - #42037

Closed
PedroHenrique0713 wants to merge 4 commits into
appsmithorg:releasefrom
PedroHenrique0713:fix/utility-bugs-round3
Closed

fix: findIndex missing return, isURL null guard, sanitizeString null guard#42037
PedroHenrique0713 wants to merge 4 commits into
appsmithorg:releasefrom
PedroHenrique0713:fix/utility-bugs-round3

Conversation

@PedroHenrique0713

@PedroHenrique0713 PedroHenrique0713 commented Jul 23, 2026

Copy link
Copy Markdown

Summary

Three bug fixes in Appsmith utilities.

# File Bug
1 JSPaneUtils.tsx findIndex callback missing return, always returned -1
2 TypeHelpers.ts isURL crashes on null/undefined from dynamic data
3 URLUtils.ts sanitizeString crashes on falsy form field values

Summary by CodeRabbit

  • Bug Fixes
    • Improved handling of names containing special characters.
    • Fixed retry failures so errors are reported consistently.
    • Improved URL validation and sanitization for empty or invalid inputs.
    • Corrected form data path generation for changed actions.
    • Prevented scrolling errors when widgets or elements are unavailable.
    • Improved array comparisons and ensured array updates do not unexpectedly alter existing data.

… lookup

fix(AppsmithUtils): escape regex special characters in getNextEntityName and
getDuplicateName. Entity name prefixes containing regex metacharacters (. $ * + etc.)
caused incorrect auto-increment numbering and potential name collisions.

fix(helpers): guard against division by zero in isElementVisibleInContainer.
When an element has zero dimensions, elementArea === 0 caused Infinity/NaN
comparisons that falsely reported the element as visible.

fix(helpers): add null guard to getWidgetElementToScroll.
Accessing widget.parentId without checking if canvasWidgets[widgetId]
exists caused TypeError on stale/deleted widget IDs.
fix(retryPromise): use reject() instead of Promise.reject() inside setTimeout.
  The setTimeout callback return value is ignored, so Promise.reject() created
  a dangling rejection that never reached the outer Promise's reject handler,
  causing the promise to hang forever when retries were exhausted.

fix(areArraysEqual): use element-wise comparison instead of join(",").
  Array elements containing commas caused false positives (e.g.,
  ["a,b"] and ["a","b"] incorrectly reported as equal).
fix(helpers): pushToArray no longer mutates input array in-place.
  Previously arr1.push(item) mutated the caller's array, violating
  immutability expectations in Redux state. Now creates a new array.

fix(getPathAndValueFromActionDiffObject): fix reduce accumulator path
  computation and early return. The reduce callback referenced the outer
  'path' variable instead of 'acc', causing path to grow incorrectly
  across multiple diff elements. The return statement was also inside
  the for loop, exiting prematurely instead of checking all elements.
fix(JSPaneUtils): add missing return to findIndex callback.
  Arrow function with curly braces returned undefined, so findIndex always
  returned -1, making the archived action lookup silently fail.

fix(TypeHelpers): add null guard to isURL before regex test.
  RegExp.prototype.test throws TypeError on null/undefined input from
  dynamic data sources.

fix(URLUtils): add null guard to sanitizeString.
  str.toLowerCase() throws TypeError on null/undefined from form fields.
@PedroHenrique0713
PedroHenrique0713 requested a review from a team as a code owner July 23, 2026 19:49
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Utility helpers now escape regex input, validate defensive cases, correct diff path handling, avoid array mutation, and safely handle missing or zero-area UI elements.

Changes

Utility hardening

Layer / File(s) Summary
Core utility safety
app/client/src/utils/AppsmithUtils.tsx, app/client/src/utils/TypeHelpers.ts, app/client/src/utils/URLUtils.ts
Name generation escapes regex metacharacters, retry failures reject directly, array comparison checks elements, and URL/string helpers guard invalid input.
Diff path resolution
app/client/src/utils/getPathAndValueFromActionDiffObject.ts, app/client/src/utils/JSPaneUtils.tsx
Diff paths use the reducer accumulator and return the first matching entry; the archived-action predicate is simplified without changing its comparison.
UI helper defenses and immutable arrays
app/client/src/utils/helpers.tsx
Visibility and widget lookup handle invalid state, while pushToArray returns a new optionally unique array without mutating its input.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Poem

Regex stars now softly sleep,
Paths find the tracks they keep.
Arrays leave no scars behind,
Missing widgets stay well-defined.
Tiny guards make helpers bright—
Safer code by morning light.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description only has a summary table and omits required sections like Fixes, Automation, Cypress results, and Communication. Add the template sections: Description with context/motivation, Fixes issue link, Automation/ok-to-test, Cypress results, and Communication checkbox.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is specific and matches the main utility bug fixes described in the PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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)
app/client/src/utils/AppsmithUtils.tsx (1)

442-442: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Sort arr2 once outside every.

[...arr2].sort() is recomputed for every element, creating unnecessary allocations and making this comparison O(n² log n) instead of O(n log n).

Suggested refactor
-  return [...arr1].sort().every((val, i) => val === [...arr2].sort()[i]);
+  const sortedArr1 = [...arr1].sort();
+  const sortedArr2 = [...arr2].sort();
+  return sortedArr1.every((val, i) => val === sortedArr2[i]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/client/src/utils/AppsmithUtils.tsx` at line 442, Update the array
comparison expression in the surrounding utility function to sort arr2 once
before calling every, then reuse the sorted result inside the callback. Preserve
the existing arr1 sorting and element-by-element equality behavior while
avoiding repeated [...arr2].sort() allocations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/client/src/utils/AppsmithUtils.tsx`:
- Around line 318-326: Update the retry logic in AppsmithUtils to immediately
reject when shouldRetry(e) is false, use retriesLeft <= 1 to terminate exhausted
retries, and pass shouldRetry into the recursive call so every retry path
settles the promise.

---

Nitpick comments:
In `@app/client/src/utils/AppsmithUtils.tsx`:
- Line 442: Update the array comparison expression in the surrounding utility
function to sort arr2 once before calling every, then reuse the sorted result
inside the callback. Preserve the existing arr1 sorting and element-by-element
equality behavior while avoiding repeated [...arr2].sort() allocations.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8e1494a0-63c4-4628-b098-aeb5f3f0da07

📥 Commits

Reviewing files that changed from the base of the PR and between 583811d and 9eb177c.

📒 Files selected for processing (6)
  • app/client/src/utils/AppsmithUtils.tsx
  • app/client/src/utils/JSPaneUtils.tsx
  • app/client/src/utils/TypeHelpers.ts
  • app/client/src/utils/URLUtils.ts
  • app/client/src/utils/getPathAndValueFromActionDiffObject.ts
  • app/client/src/utils/helpers.tsx

Comment on lines 318 to +326
if (shouldRetry(e)) {
setTimeout(async () => {
if (retriesLeft === 1) {
return Promise.reject({
reject({
code: ERROR_CODES.SERVER_ERROR,
message: createMessage(ERROR_500),
show: false,
});
return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Ensure every retry path settles the promise.

When shouldRetry(e) returns false, the outer promise remains pending. Also, retriesLeft === 1 misses zero or negative values, which can schedule retries indefinitely. Reject non-retryable errors immediately, use retriesLeft <= 1, and pass shouldRetry through the recursive call at Line 330.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/client/src/utils/AppsmithUtils.tsx` around lines 318 - 326, Update the
retry logic in AppsmithUtils to immediately reject when shouldRetry(e) is false,
use retriesLeft <= 1 to terminate exhausted retries, and pass shouldRetry into
the recursive call so every retry path settles the promise.

@PedroHenrique0713

Copy link
Copy Markdown
Author

Closing this one. I opened a stack of PRs in this repo today and, because each branch was cut from the previous one instead of from the base, they overlap: this PR carries the commits of the earlier ones as well. I am consolidating the work in #42033 and will resubmit the remaining fixes individually, on top of the base branch, once that one has been reviewed. Sorry for the noise.

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.

1 participant