Skip to content

feat(cli): extract QuotaContext and resolve infinite render loop#24959

Merged
Adib234 merged 12 commits intomainfrom
adibakm/investigate-minified-react-error
Apr 13, 2026
Merged

feat(cli): extract QuotaContext and resolve infinite render loop#24959
Adib234 merged 12 commits intomainfrom
adibakm/investigate-minified-react-error

Conversation

@Adib234
Copy link
Copy Markdown
Contributor

@Adib234 Adib234 commented Apr 8, 2026

Summary

Resolved the fatal 'Maximum update depth exceeded' React error (Crash #185) that occurred during high-volume terminal output or shell tool execution.

Details

The investigation revealed that high-frequency state updates (specifically quota stats and error counts) were triggering global UI re-renders because of an unstable quota object literal inside the root UIStateContext. This created a synchronous feedback loop with layout measurements.

Key Changes:

  • Extracted QuotaContext: Created a dedicated context to isolate quota state (userTier, stats, proQuotaRequest, etc.). This ensures that post-message quota updates no longer trigger a full-app re-render.
  • Memoized Global State: Stabilized the uiState object in AppContainer.tsx by removing unstable object literals and ensuring proper memoization.
  • Removed Debug Overhead: Deleted the useTraceUpdate hook and all temporary investigation logging ([DEBUG_LOOP]) to clean up the codebase and debug.log.
  • Refactored Consumers: Updated Footer, DialogManager, and useComposerStatus to use the new useQuotaState hook.
  • Comprehensive Test Coverage: Updated the test rig and all affected component tests to support the new provider hierarchy.

Related Issues

Fixes #24917

How to Validate

  1. Run a shell command with heavy output (e.g., ! find .).
  2. Verify that the CLI no longer crashes with a maximum update depth error.
  3. Verify that all UI tests (npm test -w @google/gemini-cli) pass.

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (All 223 UI tests passing)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx

@Adib234 Adib234 requested a review from a team as a code owner April 8, 2026 20:16
@gemini-code-assist

This comment was marked as outdated.

gemini-code-assist[bot]

This comment was marked as outdated.

@google-gemini google-gemini deleted a comment from gemini-cli bot Apr 8, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 8, 2026

Size Change: +616 B (0%)

Total Size: 34.1 MB

Filename Size Change
./bundle/chunk-6C7YLK4P.js 0 B -14.8 MB (removed) 🏆
./bundle/chunk-BXVQSWCV.js 0 B -3.16 MB (removed) 🏆
./bundle/chunk-LLYV7VFQ.js 0 B -3.8 kB (removed) 🏆
./bundle/core-FXRURLCV.js 0 B -46.2 kB (removed) 🏆
./bundle/devtoolsService-ZTKV6TJM.js 0 B -28.4 kB (removed) 🏆
./bundle/gemini-AMOSQJZ2.js 0 B -552 kB (removed) 🏆
./bundle/interactiveCli-5Y5TDVYT.js 0 B -1.66 MB (removed) 🏆
./bundle/oauth2-provider-R3B2AWKF.js 0 B -9.16 kB (removed) 🏆
./bundle/chunk-AJ5M2C6F.js 3.16 MB +3.16 MB (new file) 🆕
./bundle/chunk-F7OXSOBE.js 14.8 MB +14.8 MB (new file) 🆕
./bundle/chunk-FPHBKJ5F.js 3.8 kB +3.8 kB (new file) 🆕
./bundle/core-NWLAGIRO.js 46.2 kB +46.2 kB (new file) 🆕
./bundle/devtoolsService-EEH5X3X4.js 28.4 kB +28.4 kB (new file) 🆕
./bundle/gemini-52V2NS6J.js 552 kB +552 kB (new file) 🆕
./bundle/interactiveCli-SLIGHXED.js 1.66 MB +1.66 MB (new file) 🆕
./bundle/oauth2-provider-G2F2BTZR.js 9.16 kB +9.16 kB (new file) 🆕
ℹ️ View Unchanged
Filename Size Change
./bundle/bundled/third_party/index.js 8 MB 0 B
./bundle/chunk-34MYV7JD.js 2.45 kB 0 B
./bundle/chunk-5AUYMPVF.js 858 B 0 B
./bundle/chunk-5PS3AYFU.js 1.18 kB 0 B
./bundle/chunk-664ZODQF.js 124 kB 0 B
./bundle/chunk-DAHVX5MI.js 206 kB 0 B
./bundle/chunk-IUUIT4SU.js 56.5 kB 0 B
./bundle/chunk-P52CHEF3.js 1.96 MB 0 B
./bundle/chunk-RJTRUG2J.js 39.8 kB 0 B
./bundle/cleanup-5EK22CZ3.js 0 B -932 B (removed) 🏆
./bundle/devtools-36NN55EP.js 696 kB 0 B
./bundle/dist-T73EYRDX.js 356 B 0 B
./bundle/events-XB7DADIJ.js 418 B 0 B
./bundle/gemini.js 4.97 kB 0 B
./bundle/getMachineId-bsd-TXG52NKR.js 1.55 kB 0 B
./bundle/getMachineId-darwin-7OE4DDZ6.js 1.55 kB 0 B
./bundle/getMachineId-linux-SHIFKOOX.js 1.34 kB 0 B
./bundle/getMachineId-unsupported-5U5DOEYY.js 1.06 kB 0 B
./bundle/getMachineId-win-6KLLGOI4.js 1.72 kB 0 B
./bundle/memoryDiscovery-23MICZEL.js 980 B 0 B
./bundle/multipart-parser-KPBZEGQU.js 11.7 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js 222 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js 229 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js 13.4 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/types.js 132 B 0 B
./bundle/sandbox-macos-permissive-open.sb 890 B 0 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB 0 B
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB 0 B
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB 0 B
./bundle/sandbox-macos-strict-open.sb 4.82 kB 0 B
./bundle/sandbox-macos-strict-proxied.sb 5.02 kB 0 B
./bundle/src-QVCVGIUX.js 47 kB 0 B
./bundle/tree-sitter-7U6MW5PS.js 274 kB 0 B
./bundle/tree-sitter-bash-34ZGLXVX.js 1.84 MB 0 B
./bundle/cleanup-6NU2KQXG.js 932 B +932 B (new file) 🆕

compressed-size-action

@Adib234

This comment was marked as outdated.

@gemini-cli gemini-cli bot added the area/core Issues related to User Interface, OS Support, Core Functionality label Apr 8, 2026
@Adib234 Adib234 self-assigned this Apr 8, 2026
Copy link
Copy Markdown
Contributor

@jacob314 jacob314 left a comment

Choose a reason for hiding this comment

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

lgtm

@Adib234 Adib234 enabled auto-merge April 8, 2026 20:49
@Adib234 Adib234 disabled auto-merge April 8, 2026 20:57
Adib234 and others added 6 commits April 9, 2026 14:42
This change isolates quota-related state into a dedicated context, preventing frequent quota updates from triggering global UI re-renders. It also removes an unstable object literal in AppContainer that was causing a 'Maximum update depth exceeded' crash during shell tool execution. Includes cleanup of useTraceUpdate and temporary debug logging.
@Adib234
Copy link
Copy Markdown
Contributor Author

Adib234 commented Apr 10, 2026

/gemini review

@Adib234 Adib234 changed the title fix(cli): prevent infinite update loop in useTimedMessage feat(cli): extract QuotaContext and resolve infinite render loop Apr 10, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the CLI's state management by extracting quota-related data from UIStateContext into a new, dedicated QuotaContext. The changes include the introduction of the QuotaContext and useQuotaState hook, along with updates to several components and tests to utilize this new context. A critical issue was noted in AppContainer.tsx where the quota property is still being assigned to the uiState object, resulting in a type mismatch since the property was removed from the UIState interface.

Adib234 added 3 commits April 10, 2026 17:16
Removed duplicated QuotaState interface from UIStateContext, reverted stylistic changes in MaxSizedBox, and removed temporary fallback logic in test utilities. All tests have been migrated to use QuotaContext.
@Adib234
Copy link
Copy Markdown
Contributor Author

Adib234 commented Apr 10, 2026

Code Review

Overall, the extraction of QuotaContext is a great architectural improvement that aligns with our React guidelines by stabilizing the global state and preventing unnecessary full-app re-renders. The PR title correctly follows Conventional Commits, and the context updates in AppContainer.tsx and various consumers (Footer, DialogManager, useComposerStatus) look solid.

I did find one issue in the test utilities that needs to be addressed:

Issue in Composer.test.tsx

In packages/cli/src/ui/components/Composer.test.tsx, quotaState is being constructed by casting uiState to QuotaState:

  const quotaState: QuotaState = {
    userTier: (uiState as unknown as QuotaState).userTier,
    stats: (uiState as unknown as QuotaState).stats,
    proQuotaRequest: (uiState as unknown as QuotaState).proQuotaRequest,
    validationRequest: (uiState as unknown as QuotaState).validationRequest,
  };

This violates our strict typing rules for tests (Avoid using any in tests; prefer proper types or unknown with narrowing). More importantly, it is logically flawed: because quota has been removed from UIState and createMockUIState, these properties are no longer present on uiState, meaning they will just evaluate to undefined at runtime.

Recommendation:
Instead of extracting these from uiState, provide an explicit default quotaState and add an optional quotaStateOverrides: Partial<QuotaState> = {} parameter to renderComposer.

const renderComposer = async (
  uiStateOverrides: Partial<UIState> = {},
  inputStateOverrides: Partial<InputState> = {},
  quotaStateOverrides: Partial<QuotaState> = {},
) => {
  // ...
  const quotaState: QuotaState = {
    userTier: undefined,
    stats: undefined,
    proQuotaRequest: null,
    validationRequest: null,
    overageMenuRequest: null,
    emptyWalletRequest: null,
    ...quotaStateOverrides,
  };
  // ...
}

Once this test utility is cleaned up, this PR is good to go!

Copy link
Copy Markdown
Contributor

@jacob314 jacob314 left a comment

Choose a reason for hiding this comment

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

lgtm

Approved with a nit about the Composer.test.tx performing casts that should always return undefined.

@Adib234 Adib234 enabled auto-merge April 13, 2026 17:59
@Adib234 Adib234 added this pull request to the merge queue Apr 13, 2026
Merged via the queue into main with commit b91d177 Apr 13, 2026
27 checks passed
@Adib234 Adib234 deleted the adibakm/investigate-minified-react-error branch April 13, 2026 19:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core Issues related to User Interface, OS Support, Core Functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

User getting the ERROR Minified React error #185

2 participants