Skip to content

fix: add safety check to fileTree memoization - #537

Open
Somil450 wants to merge 1 commit into
piyushdotcomm:mainfrom
Somil450:fix/527-memoize-collect-file-paths
Open

fix: add safety check to fileTree memoization#537
Somil450 wants to merge 1 commit into
piyushdotcomm:mainfrom
Somil450:fix/527-memoize-collect-file-paths

Conversation

@Somil450

Copy link
Copy Markdown

Summary

Closes #527
Adds a safety check to the fileTree memoization block in ai-chat-panel.tsx to ensure templateData.items is defined before traversing it.

Context

The original issue called out that collectFilePaths() was being run on every render. However, a recent refactor had actually already wrapped it in useMemo.

This PR "officially" closes the issue by making that existing memoization robust. The previous code checked if templateData existed, but not if the items array was populated. If the object structure was incomplete, collectFilePaths would crash the chat panel.

Change

// modules/playground/components/ai-chat-panel.tsx

- () => templateData ? collectFilePaths(templateData.items).join("\n") : "",
+ () => templateData?.items ? collectFilePaths(templateData.items).join("\n") : "",

Closes piyushdotcomm#527

collectFilePaths was recently wrapped in useMemo to prevent per-render
traversal. This commit adds a safety check to ensure templateData.items
exists before calling the function, preventing potential crashes if the
template object structure is incomplete.
@Somil450
Somil450 requested a review from piyushdotcomm as a code owner July 31, 2026 09:25
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@Somil450, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 16 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7a7cc467-b756-421c-954b-9bac1e8f8f94

📥 Commits

Reviewing files that changed from the base of the PR and between 4ffe26f and fd67897.

📒 Files selected for processing (1)
  • modules/playground/components/ai-chat-panel.tsx

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.

@github-actions

Copy link
Copy Markdown

👋 Thanks for opening a PR, @Somil450!

Your PR has entered the 🚦 PR Review Pipeline.

Standard PR detected — your PR will follow the standard review pipeline.


What happens next

Stage Reviewer Checks
Stage 1 — Automated Validation 🤖 Bot DCO · Format · AI/Slop · Duplicate
Stage 2 — Human Review 👥 Maintainer Code + Quality Review
Stage 3 — PA / Maintainer Review 🔑 Project Admin Final Merge Decision

A pipeline status comment will appear below and update automatically as your PR progresses.


While you wait

  • Sign all commits (git commit -s)
  • Link your issue (Closes #123)
  • Use a feature branch (not main)
  • Avoid unrelated changes

This comment is posted only once.

@github-actions github-actions Bot added the bug Something isn't working label Jul 31, 2026
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Fix fileTree memoization crash when templateData.items is missing

🐞 Bug fix 🕐 Less than 5 minutes

Grey Divider

AI Description

• Guard file tree memoization against missing template items.
• Prevent AI chat panel crashes when template data shape is incomplete.
Diagram

graph TD
A["AIChatPanel"] --> B["useMemo(fileTree)"] --> C{"templateData.items?"}
C -->|"Yes"| D["collectFilePaths(items)"] --> E["fileTree string"]
C -->|"No"| E
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Make collectFilePaths() accept undefined/empty input
  • ➕ Centralizes defensive behavior at the traversal boundary
  • ➕ Reduces repeated guards at call sites
  • ➖ Can hide upstream data-shape issues
  • ➖ May require changing function signature/types and updating other callers
2. Normalize templateData shape when loading/creating it
  • ➕ Ensures all consumers can rely on templateData.items existing
  • ➕ Improves invariants across the playground module
  • ➖ Bigger scope; requires tracking all creation/loading paths
  • ➖ Harder to justify for a single crash-site fix

Recommendation: Keep the current approach: guarding at the memoization call site is the smallest, clearest fix aligned with the reported crash scenario. If similar checks start spreading to multiple call sites, consider moving the guard into collectFilePaths() or enforcing a normalized templateData schema upstream.

Files changed (1) +1 / -1

Bug fix (1) +1 / -1
ai-chat-panel.tsxGuard fileTree memoization against missing templateData.items +1/-1

Guard fileTree memoization against missing templateData.items

• Updates the fileTree useMemo callback to check templateData.items before calling collectFilePaths(). This prevents runtime errors when templateData exists but the items array is undefined.

modules/playground/components/ai-chat-panel.tsx

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (1) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 22 rules

Grey Divider


Remediation recommended

1. Items not array-guarded 🐞 Bug ☼ Reliability
Description
The new templateData?.items check only tests truthiness, so a truthy non-array items value can
still be passed to collectFilePaths(...) and throw during the for...of traversal. AIChatPanel
tool handlers also pass templateData.items into helpers that assume arrays, so malformed DB-parsed
template data can still crash later during tool execution.
Code

modules/playground/components/ai-chat-panel.tsx[85]

+        () => templateData?.items ? collectFilePaths(templateData.items).join("\n") : "",
Relevance

●●● Strong

Team previously accepted adding Array.isArray guards in ai-chat-panel to prevent runtime crashes.

PR-#236

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
templateData is sourced from unvalidated JSON (JSON.parse(rawContent)), so it can be missing
required fields like items. The updated memoization condition only checks truthiness and then
calls collectFilePaths, which assumes it receives an array (uses for...of). Separately, the tool
handlers call helpers with templateData.items after only checking templateData is non-null, so
missing/invalid items can still throw at runtime when tools run.

modules/playground/components/ai-chat-panel.tsx[83-87]
modules/playground/components/ai-chat-panel.tsx[207-292]
modules/playground/actions/index.ts[121-156]
modules/playground/hooks/useAI.ts[145-157]
modules/playground/lib/path-to-json.ts[23-26]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`AIChatPanel` now checks `templateData?.items` before building `fileTree`, but this is only a truthy check. If `templateData` is malformed (e.g., parsed from DB JSON without `items`, or with `items` not being an array), the chat panel can still crash:
- In the `fileTree` memoization, by calling `collectFilePaths` with a non-array.
- In tool handlers (edit/delete), by passing `templateData.items` into helpers that expect arrays.

## Issue Context
`getPlaygroundById` parses template JSON from the DB without validating that it matches the expected `TemplateFolder` schema (including `items: TemplateItem[]`). This makes runtime malformed data plausible even if TypeScript types say otherwise.

## Fix Focus Areas
- modules/playground/components/ai-chat-panel.tsx[83-87]
- modules/playground/components/ai-chat-panel.tsx[207-292]
- modules/playground/actions/index.ts[121-156]
- modules/playground/hooks/useAI.ts[145-157]

## Suggested fix
1. Normalize once in `AIChatPanel`:
  - `const templateItems = Array.isArray(templateData?.items) ? templateData.items : [];`
2. Build `fileTree` from `templateItems`:
  - `useMemo(() => collectFilePaths(templateItems).join("\n"), [templateItems])`
3. In tool handlers, use `templateItems` (or guard with `Array.isArray(templateData?.items)` and return a user-friendly error) before calling `addOrUpdateFile/deleteFileByPath/findFileByPath`.
4. (Optional but stronger) Validate/repair the parsed DB JSON in `getPlaygroundById` (e.g., if parsed object lacks `items`, set `items: []` or treat it as invalid and fall back to scanning).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. ai-chat-panel.tsx over 500 lines 📘 Rule violation ⚙ Maintainability
Description
modules/playground/components/ai-chat-panel.tsx is 510 lines long, exceeding the 500-line maximum.
This increases maintenance overhead and makes the component harder to review and safely evolve.
Code

modules/playground/components/ai-chat-panel.tsx[85]

+        () => templateData?.items ? collectFilePaths(templateData.items).join("\n") : "",
Relevance

●● Moderate

No clear precedent on enforcing 500-line file splits; requires larger refactor beyond PR’s scope.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The checklist requires individual source files to be at most 500 lines. The file’s last line number
is 510 in the PR branch, demonstrating it exceeds the limit.

Rule 599989: Limit individual source files to 500 lines maximum
modules/playground/components/ai-chat-panel.tsx[481-510]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`modules/playground/components/ai-chat-panel.tsx` exceeds the 500-line limit (currently 510 lines), violating the project file-size compliance requirement.

## Issue Context
This PR modifies the file, so it is in the changed-path set and must comply with the 500-line cap.

## Fix Focus Areas
- modules/playground/components/ai-chat-panel.tsx[1-510]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

// Memoize the file tree string to avoid re-computing on every render
const fileTree = useMemo(
() => templateData ? collectFilePaths(templateData.items).join("\n") : "",
() => templateData?.items ? collectFilePaths(templateData.items).join("\n") : "",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

1. Ai-chat-panel.tsx over 500 lines 📘 Rule violation ⚙ Maintainability

modules/playground/components/ai-chat-panel.tsx is 510 lines long, exceeding the 500-line maximum.
This increases maintenance overhead and makes the component harder to review and safely evolve.
Agent Prompt
## Issue description
`modules/playground/components/ai-chat-panel.tsx` exceeds the 500-line limit (currently 510 lines), violating the project file-size compliance requirement.

## Issue Context
This PR modifies the file, so it is in the changed-path set and must comply with the 500-line cap.

## Fix Focus Areas
- modules/playground/components/ai-chat-panel.tsx[1-510]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

// Memoize the file tree string to avoid re-computing on every render
const fileTree = useMemo(
() => templateData ? collectFilePaths(templateData.items).join("\n") : "",
() => templateData?.items ? collectFilePaths(templateData.items).join("\n") : "",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

2. Items not array-guarded 🐞 Bug ☼ Reliability

The new templateData?.items check only tests truthiness, so a truthy non-array items value can
still be passed to collectFilePaths(...) and throw during the for...of traversal. AIChatPanel
tool handlers also pass templateData.items into helpers that assume arrays, so malformed DB-parsed
template data can still crash later during tool execution.
Agent Prompt
## Issue description
`AIChatPanel` now checks `templateData?.items` before building `fileTree`, but this is only a truthy check. If `templateData` is malformed (e.g., parsed from DB JSON without `items`, or with `items` not being an array), the chat panel can still crash:
- In the `fileTree` memoization, by calling `collectFilePaths` with a non-array.
- In tool handlers (edit/delete), by passing `templateData.items` into helpers that expect arrays.

## Issue Context
`getPlaygroundById` parses template JSON from the DB without validating that it matches the expected `TemplateFolder` schema (including `items: TemplateItem[]`). This makes runtime malformed data plausible even if TypeScript types say otherwise.

## Fix Focus Areas
- modules/playground/components/ai-chat-panel.tsx[83-87]
- modules/playground/components/ai-chat-panel.tsx[207-292]
- modules/playground/actions/index.ts[121-156]
- modules/playground/hooks/useAI.ts[145-157]

## Suggested fix
1. Normalize once in `AIChatPanel`:
   - `const templateItems = Array.isArray(templateData?.items) ? templateData.items : [];`
2. Build `fileTree` from `templateItems`:
   - `useMemo(() => collectFilePaths(templateItems).join("\n"), [templateItems])`
3. In tool handlers, use `templateItems` (or guard with `Array.isArray(templateData?.items)` and return a user-friendly error) before calling `addOrUpdateFile/deleteFileByPath/findFileByPath`.
4. (Optional but stronger) Validate/repair the parsed DB JSON in `getPlaygroundById` (e.g., if parsed object lacks `items`, set `items: []` or treat it as invalid and fall back to scanning).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Performance] Memoize collectFilePaths() in AI Chat Panel to avoid per-render traversal

2 participants