Skip to content

fix(frontend): resolve the refractor chunk failure that remounts the playground and closes the Advanced drawer#5323

Open
mmabrouk wants to merge 1 commit into
mainfrom
fix-advanced-drawer-remount
Open

fix(frontend): resolve the refractor chunk failure that remounts the playground and closes the Advanced drawer#5323
mmabrouk wants to merge 1 commit into
mainfrom
fix-advanced-drawer-remount

Conversation

@mmabrouk

@mmabrouk mmabrouk commented Jul 14, 2026

Copy link
Copy Markdown
Member

Symptom

In the agent playground, opening the Configuration panel's Advanced drawer and
clicking a section row ("Execution environment" or "Permissions") intermittently
(~1-in-4) closed the whole drawer instead of expanding the section. In one case the click
fell through the closing overlay and opened the Turn inspector for an off-screen chat turn.
Repro and evidence: docs/design/agent-workflows/projects/qa/ui-exploration-20260714.md
(bug 2).

Console evidence captured at every failure

  • [EXCEPTION] Error: Cannot find module 'refractor/all' from a lazy-loaded chunk,
    each time followed by a duplicate burst of app-boot console lines (organizations
    fetches, atomFamily/loadable deprecation warnings) — the signature of a partial React
    tree remount.
  • [WARNING] Detected store mutation during atom read (Jotai) — a separate anti-pattern,
    not the cause here (see follow-up below).

Root cause

web/oss/next.config.ts registered a production-only webpack IgnorePlugin:

new webpack.IgnorePlugin({
    resourceRegExp: /^refractor\/.+$/,
    contextRegExp: /react-syntax-highlighter/,
})

It stubbed out every refractor/* import made by react-syntax-highlighter,
including refractor/all. The agent chat markdown renderer
(web/oss/src/components/AgentChatSlice/assets/markdown.tsx) highlights fenced code
blocks with PrismAsync, which at runtime does a dynamic
import('refractor/all') to load languages on demand. With the import stubbed, that
lazy chunk threw Cannot find module 'refractor/all' the first time a chat message with
a code block rendered.

Causal chain (drawer close)

  1. A chat turn renders a fenced code block → PrismAsync dynamically imports
    refractor/all.
  2. The IgnorePlugin-stubbed chunk throws Cannot find module 'refractor/all'.
  3. The Layout error boundary (web/oss/src/components/Layout/Layout.tsx wraps the page
    {children} in <ErrorBoundary>) catches it and remounts the playground subtree
    (the duplicate app-boot burst).
  4. The open Advanced drawer is a descendant of that subtree, so it unmounts — the drawer
    "closes" instead of the section expanding.

Why intermittent (~25%): the throw only fires when the visible chat content contains
a fenced code block whose language triggers PrismAsync's refractor/all load. Turns
without a code block never hit the broken chunk, so only some interactions repro.

Click fall-through: a consequence of the same remount — during the unmount window the
drawer overlay is gone, so the click lands on whatever is behind it (the off-screen Turn
inspector). No separate fix needed.

The plugin was stale: refractor@5.0.0 is installed and resolves every subpath rsh
imports — all 297 async languages plus ./all and ./core (0 missing). The comment even
claimed it was about "@ant-design/x that we don't use", but the refractor entry was scoped
to react-syntax-highlighter, which the app does use.

Fix

Remove the refractor IgnorePlugin (keep the legitimate mermaid one for
@ant-design/x). The dynamic refractor/all chunk now resolves and loads, so no
exception, no error-boundary remount, and the drawer stays open.

Before / after

  • Before: production build stubs refractor/all → chat code block render throws →
    playground remounts → Advanced drawer closes on section click (~1-in-4).
  • After: refractor/all loads as a lazy chunk → code blocks highlight normally →
    no remount → drawer sections expand as expected.

web/ee/next.config.ts imports the OSS config, so this single change covers both editions.

Verification

  • Confirmed refractor@5.0.0 exports ./all, ./core, and every one of the 297 language
    subpaths react-syntax-highlighter@16.1.1 async-imports (diffed the two package trees:
    zero missing).
  • Confirmed the webpack branch (and thus the IgnorePlugin) applies only to production
    builds (!isDevelopment), matching the live repro on a deployed build and explaining why
    dev/turbopack never showed it.
  • Production build verified clean: ran pnpm build-oss (webpack production branch,
    NODE_ENV=production) with the plugin removed — exit 0, all 7 turbo tasks successful,
    no refractor/rsh resolution errors, so the plugin's original "prevent build errors"
    motivation did not resurface. The emitted chunk 79590.* (the exact chunk number that
    threw Cannot find module 'refractor/all' in the QA capture) now weighs ~380K and
    contains the refractor language definitions instead of a stub.
  • prettier --write on the touched file: unchanged.

Manual verification (deployed build, per the findings doc): open an agent playground, send
a message that renders a fenced code block, then open the Advanced drawer and click
"Execution environment" / "Permissions" repeatedly through several open/close cycles. The
section should expand every time with no Cannot find module 'refractor/all' exception and
no drawer self-dismiss.

Follow-up (out of scope)

The Jotai Detected store mutation during atom read warning is a separate state
anti-pattern, not the cause of this remount. Left untouched here; worth a dedicated pass.

https://claude.ai/code/session_01Hyn9365BLPXDmNZShrQkmH

…playground and closes the Advanced drawer

The production webpack build stubbed out react-syntax-highlighter's dynamic
import of refractor/all via an IgnorePlugin. When the agent chat markdown
renderer (AgentChatSlice/assets/markdown.tsx, PrismAsync) highlighted a fenced
code block, that ignored chunk threw "Cannot find module 'refractor/all'",
tripping the Layout error boundary and remounting the playground subtree, which
unmounted the open Advanced drawer.

refractor@5 is installed and resolves every subpath rsh imports (all 297
languages plus /all and /core), so the ignore was stale and purely harmful.
Remove it so the chunk loads.

Claude-Session: https://claude.ai/code/session_01Hyn9365BLPXDmNZShrQkmH
@mmabrouk

Copy link
Copy Markdown
Member Author

@coderabbitai review

@dosubot dosubot Bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Jul 14, 2026
@vercel

vercel Bot commented Jul 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment Jul 14, 2026 9:14pm

Request Review

@dosubot dosubot Bot added Bug Report Something isn't working Frontend UI labels Jul 14, 2026
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The non-development Next.js Webpack configuration now ignores only mermaid imports. The previous refractor/* ignore rule was removed, and comments document why those imports must remain intact.

Changes

Webpack import handling

Layer / File(s) Summary
Restrict ignored ESM imports
web/oss/next.config.ts
The IgnorePlugin configuration continues to ignore mermaid while preserving refractor/* imports used by code rendering.

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

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Title check ✅ Passed The title clearly describes the main fix: removing the refractor chunk failure that remounted the playground and closed the Advanced drawer.
Description check ✅ Passed The description is directly about the same refractor IgnorePlugin bug, its cause, fix, and verification, so it matches the changeset.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-advanced-drawer-remount

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 commented Jul 14, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
web/oss/next.config.ts (1)

144-148: 📐 Maintainability & Code Quality | 🔵 Trivial

Consider Turbopack compatibility for custom ignores.

While this webpack.IgnorePlugin configuration works correctly for Webpack builds, Next.js 15 (as of 15.4+) is stabilizing Turbopack as the production bundler (next build --turbopack). Custom Webpack plugins added to next.config.ts are completely ignored by Turbopack. If the project eventually migrates to Turbopack, you will need to replace this plugin with Turbopack-compatible configurations (e.g., using experimental.turbo.resolveAlias or marking the module as external).


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7bc4b6cb-deb2-41cf-a2a0-2cefcdc7cd78

📥 Commits

Reviewing files that changed from the base of the PR and between 2853e37 and a31b88e.

📒 Files selected for processing (1)
  • web/oss/next.config.ts

Comment thread web/oss/next.config.ts
Comment on lines +138 to +143
// Ignore the mermaid import from @ant-design/x — we don't use that surface.
// NOTE: do not ignore `refractor/*` here. react-syntax-highlighter's PrismAsync
// dynamically imports `refractor/all` at runtime; stubbing it out throws
// "Cannot find module 'refractor/all'" when a chat code block renders, which trips
// the app error boundary and remounts the playground. refractor@5 resolves every
// subpath rsh imports, so the import must be left intact.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Condense the inline comment to comply with guidelines.

The explanation is valid and highlights a genuinely surprising constraint, but it spans six lines. As per coding guidelines, keep in-code comments to one short line maximum unless a genuinely surprising constraint requires a brief exception. The comment can be significantly shortened while retaining the core warning about the runtime constraints.

♻️ Proposed fix
-                  // Ignore the mermaid import from `@ant-design/x` — we don't use that surface.
-                  // NOTE: do not ignore `refractor/*` here. react-syntax-highlighter's PrismAsync
-                  // dynamically imports `refractor/all` at runtime; stubbing it out throws
-                  // "Cannot find module 'refractor/all'" when a chat code block renders, which trips
-                  // the app error boundary and remounts the playground. refractor@5 resolves every
-                  // subpath rsh imports, so the import must be left intact.
+                  // Ignore unused mermaid. Do not ignore `refractor/*`; react-syntax-highlighter requires it at runtime to prevent code block rendering crashes.
📝 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
// Ignore the mermaid import from @ant-design/x — we don't use that surface.
// NOTE: do not ignore `refractor/*` here. react-syntax-highlighter's PrismAsync
// dynamically imports `refractor/all` at runtime; stubbing it out throws
// "Cannot find module 'refractor/all'" when a chat code block renders, which trips
// the app error boundary and remounts the playground. refractor@5 resolves every
// subpath rsh imports, so the import must be left intact.
// Ignore unused mermaid. Do not ignore `refractor/*`; react-syntax-highlighter requires it at runtime to prevent code block rendering crashes.

Source: Coding guidelines

@github-actions

Copy link
Copy Markdown
Contributor

Railway Preview Environment

Image tag pr-5323-74ea092
Status Failed
Railway logs Open logs
Logs View workflow run
Updated at 2026-07-14T21:44:03.166Z

@mmabrouk
mmabrouk requested a review from ardaerzin July 15, 2026 09:11
@mmabrouk
mmabrouk changed the base branch from release/v0.105.0 to main July 15, 2026 19:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Report Something isn't working Frontend size:S This PR changes 10-29 lines, ignoring generated files. UI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant