Skip to content

Comments

Fix: PWA cache crash#794

Merged
gsxdsm merged 1 commit intoAutoMaker-Org:v0.15.0rcfrom
gsxdsm:fix/pwa-cache-fix
Feb 21, 2026
Merged

Fix: PWA cache crash#794
gsxdsm merged 1 commit intoAutoMaker-Org:v0.15.0rcfrom
gsxdsm:fix/pwa-cache-fix

Conversation

@gsxdsm
Copy link
Collaborator

@gsxdsm gsxdsm commented Feb 21, 2026

Fix crash on PWA worktree deletion

Summary by CodeRabbit

  • New Features

    • Added automatic crash-loop protection that detects repeated crashes and provides enhanced recovery options, including a dedicated "Clear Cache & Reload" action to help resolve persistent issues.
  • Bug Fixes

    • Improved cache restoration to prevent stale project workspace selections from being reapplied, reducing unexpected workspace changes when restarting the application.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @gsxdsm, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical issue where the Progressive Web App (PWA) would crash in a loop, particularly after worktree deletions, due to attempting to restore stale cached worktree paths. The changes introduce robust crash loop detection and an automatic cache-clearing mechanism within the error boundary. Additionally, the UI cache restoration process has been made more resilient by sanitizing cached worktree selections, ensuring that only valid, non-stale data is restored, thereby preventing future crashes related to invalid worktree states.

Highlights

  • Crash Loop Detection and Auto-Recovery: Implemented a crash loop detection mechanism within the AppErrorBoundary that monitors for multiple crashes within a short timeframe. If a crash loop is detected (3 crashes in 30 seconds), the application's UI cache is automatically cleared to break the loop, preventing persistent errors caused by stale cached data.
  • Sanitized Worktree Cache Restoration: Modified the UI cache restoration logic to only restore 'main branch' worktree selections (where path is null). This prevents the application from attempting to restore stale worktree paths that may no longer exist on disk, which was a primary cause of the PWA crashing after worktree deletion.
  • Enhanced Error Boundary UI: Updated the error boundary display to provide a more informative message when a crash loop is detected, indicating that the cache has been cleared. A new 'Clear Cache & Reload' button was also added, allowing users to manually clear the UI cache and reload the application.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • apps/ui/src/components/ui/app-error-boundary.tsx
    • Added isCrashLoop state to track crash loop status.
    • Introduced constants for crash loop detection thresholds and window.
    • Implemented logic in componentDidCatch to record crash timestamps and detect crash loops.
    • Automatically cleared automaker-ui-cache from localStorage and crash timestamps from sessionStorage upon crash loop detection.
    • Added a new handleClearCacheAndReload method to clear the UI cache and reload the page.
    • Updated the error message displayed to the user to differentiate between general errors and crash loops.
    • Added a 'Clear Cache & Reload' button to the error screen.
  • apps/ui/src/store/ui-cache-store.ts
    • Modified restoreFromUICache to sanitize cachedCurrentWorktreeByProject entries.
    • Ensured that only worktree selections with a null path (main branch) are restored, dropping non-null paths to prevent issues with stale worktree directories.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link

coderabbitai bot commented Feb 21, 2026

📝 Walkthrough

Walkthrough

This change adds crash-loop detection and recovery to the error boundary component, and sanitizes the cached worktree selection in the UI cache store to prevent restoring stale or invalid worktree references.

Changes

Cohort / File(s) Summary
Crash-Loop Protection
apps/ui/src/components/ui/app-error-boundary.tsx
Introduces crash tracking with timestamp recording in sessionStorage, threshold-based detection, and conditional UI rendering that branches on crash-loop state. Adds new state field, derived state method returning Partial<State>, cache-clearing handler, and dual-action recovery UI (Reload Page and Clear Cache & Reload).
Cache Sanitization
apps/ui/src/store/ui-cache-store.ts
Modifies worktree restoration to filter cached entries, preserving only null paths (main branch) and discarding non-null (on-disk) paths. Conditional application ensures invalid or stale worktree selections are not restored.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰✨ A brave little rabbit hops through the code,
Patching the crashes that once might corrode,
With timestamp whiskers and cache-clearing might,
Loop-proof protection shines brave and bright! 🔄💫

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Fix: PWA cache crash' is related to the changeset but is overly broad and partially generic. It doesn't clearly specify that the fix addresses crash-loop protection and stale worktree cache sanitization. Consider a more specific title that reflects the main changes, such as 'Add crash-loop protection and sanitize cached worktrees' to better convey the actual implementation details.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 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

@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 effectively addresses a PWA crash loop caused by stale worktree paths in the cache. The solution is two-pronged: first, it introduces a robust crash loop detection in the AppErrorBoundary to automatically clear the cache after repeated crashes. Second, it fixes the root cause by sanitizing the ui-cache-store on restore, ensuring only safe worktree selections are loaded. The implementation is solid. I've included a couple of suggestions to enhance code maintainability and readability.

/** Number of crashes within the time window that constitutes a crash loop */
const CRASH_LOOP_THRESHOLD = 3;
/** Time window in ms for crash loop detection (30 seconds) */
const CRASH_LOOP_WINDOW_MS = 30_000;
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

To avoid using a magic string for the UI cache key ('automaker-ui-cache'), it's good practice to define it as a constant here, alongside the other constants. This key is used in componentDidCatch and handleClearCacheAndReload.

After adding this constant, you can replace the hardcoded string in both places.

const CRASH_LOOP_WINDOW_MS = 30_000;

/** Key for the UI cache in localStorage, used for clearing on crash loops. */
const UI_CACHE_KEY = 'automaker-ui-cache';

Comment on lines +175 to +187
const sanitized: Record<string, { path: string | null; branch: string }> = {};
for (const [projectPath, worktree] of Object.entries(cache.cachedCurrentWorktreeByProject)) {
if (worktree.path === null) {
// Main branch selection — always safe to restore
sanitized[projectPath] = worktree;
}
// Non-null paths are dropped; the app will re-discover actual worktrees
// from the server and the validation effect in use-worktrees will handle
// resetting to main if the cached worktree no longer exists.
}
if (Object.keys(sanitized).length > 0) {
stateUpdate.currentWorktreeByProject = sanitized;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This logic for sanitizing the worktree cache can be written more concisely using functional programming constructs like filter and Object.fromEntries. This improves readability by making the intent of filtering and creating a new object more explicit.

    // Main branch selection — always safe to restore
    const sanitizedEntries = Object.entries(cache.cachedCurrentWorktreeByProject).filter(
      ([, worktree]) => worktree.path === null
    );

    if (sanitizedEntries.length > 0) {
      stateUpdate.currentWorktreeByProject = Object.fromEntries(sanitizedEntries);
    }
    // Non-null paths are dropped; the app will re-discover actual worktrees
    // from the server and the validation effect in use-worktrees will handle
    // resetting to main if the cached worktree no longer exists.

Copy link

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

🧹 Nitpick comments (1)
apps/ui/src/components/ui/app-error-boundary.tsx (1)

71-71: Consider extracting the 'automaker-ui-cache' key to avoid magic string duplication.

The literal 'automaker-ui-cache' appears here in two places (lines 71 and 88) and is also defined as STORE_NAME in ui-cache-store.ts. If the store name ever changes, these references will silently diverge. Consider either:

  1. Exporting STORE_NAME (or a clearUICache() helper) from the cache store and importing it here, or
  2. Defining a shared constant.
♻️ Option 1: Export a helper from the cache store

In apps/ui/src/store/ui-cache-store.ts:

+/** Clear all persisted UI cache data. Useful for crash-loop recovery. */
+export function clearUICache(): void {
+  try {
+    localStorage.removeItem(STORE_NAME);
+  } catch {
+    // localStorage may be unavailable
+  }
+}

Then in app-error-boundary.tsx:

+import { clearUICache } from '@/store/ui-cache-store';
 ...
-localStorage.removeItem('automaker-ui-cache');
+clearUICache();

Also applies to: 84-93

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ui/src/components/ui/app-error-boundary.tsx` at line 71, The hard-coded
'automaker-ui-cache' string in app-error-boundary.tsx should be replaced with a
single exported identifier from the cache module to avoid divergence: export
STORE_NAME (or a clearUICache() helper) from ui-cache-store.ts and import it
into app-error-boundary.tsx, then replace
localStorage.removeItem('automaker-ui-cache') (and any other occurrences in that
file) with use of the imported STORE_NAME (or call clearUICache()); update the
import and references in app-error-boundary.tsx so all cache key usage is driven
by the shared symbol.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/ui/src/components/ui/app-error-boundary.tsx`:
- Line 71: The hard-coded 'automaker-ui-cache' string in app-error-boundary.tsx
should be replaced with a single exported identifier from the cache module to
avoid divergence: export STORE_NAME (or a clearUICache() helper) from
ui-cache-store.ts and import it into app-error-boundary.tsx, then replace
localStorage.removeItem('automaker-ui-cache') (and any other occurrences in that
file) with use of the imported STORE_NAME (or call clearUICache()); update the
import and references in app-error-boundary.tsx so all cache key usage is driven
by the shared symbol.

@gsxdsm gsxdsm merged commit f785f12 into AutoMaker-Org:v0.15.0rc Feb 21, 2026
10 checks passed
gsxdsm added a commit to gsxdsm/automaker that referenced this pull request Feb 21, 2026
gsxdsm added a commit that referenced this pull request Feb 21, 2026
* Changes from fix/docker-compose-cors-error

* Update apps/server/src/index.ts

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Fix: Delete Worktree Crash + PR Comments + Dev Server UX Improvements (#792)

* Changes from fix/delete-worktree-hotifx

* fix: Improve bot detection and prevent UI overflow issues

- Include GitHub app-initiated comments in bot detection
- Wrap handleQuickCreateSession with useCallback to fix dependency issues
- Truncate long branch names in agent header to prevent layout overflow

* feat: Support GitHub App comments in PR review and fix session filtering

* feat: Return invalidation result from delete session handler

* fix: Improve CORS origin validation to handle wildcard correctly

* fix: Correct IPv6 localhost parsing and improve responsive UI layouts

* Changes from fix/pwa-cache-fix (#794)

* fix: Add type checking to prevent crashes from malformed cache entries

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
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