Title: Claude loses hours debugging CRA + Electron packaged app when "main" field and entry point file are out of sync
Preflight Checklist
- [x] I have searched existing issues for similar behavior reports
- [x] This report does NOT contain sensitive information (API keys, passwords, etc.)
Type of Behavior Issue
Claude made incorrect assumptions about my project
What You Asked Claude to Do
Debug a packaged Electron desktop app (CRA + electron-builder 24, Windows NSIS) where the installed .exe showed wrong behavior: default Electron menu visible, file open dialogs doing nothing, wrong app version displayed. All features worked correctly in dev mode (npm run electron:dev). Asked Claude to find why the packaged build ignored all recent code changes.
What Claude Actually Did
Spent approximately 3 hours investigating wrong theories in sequence:
- CORS policy blocking fetch() calls from file:// to http://localhost
- Electron webSecurity settings
- ASAR path resolution issues
- Port conflicts with the Express local server
- Preload script failures
- BrowserWindow.fromWebContents vs mainWindow for dialogs
- Deleted and recreated files multiple times without effect
Never directly identified the root cause. The fix was found by manually inspecting the package.json inside the ASAR bundle, which revealed the packaged app was running a completely different file than expected.
Expected Behavior
When a packaged Electron app behaves differently from dev mode and all new code seems to have no effect, Claude should immediately run this diagnostic:
node -e "
const asar = require('@electron/asar');
const pkg = asar.extractFile('dist/win-unpacked/resources/app.asar', 'package.json');
console.log(pkg.toString());
"
This reveals which file "main" actually points to at runtime inside the packaged app — and takes 30 seconds. Claude should then extract that file from the ASAR and verify its content matches the current source.
Root Cause (for Claude's awareness)
CRA-based Electron projects have a specific behavior Claude is unaware of:
- CRA's npm run build copies everything in public/ to build/
- If public/electron.js exists, build/electron.js is always recreated on every build
- electron-builder uses "main" from package.json exactly — no override, no auto-detection
The project originally had "main": "build/electron.js" (standard CRA boilerplate). During a refactor, main process code was moved to electron/main.js but "main" in package.json was never updated. The old boilerplate in public/electron.js kept being copied to build/electron.js and silently ran in every packaged build — with no error, no
warning, and a fully functional-looking UI.
The symptoms (menu visible, dialogs broken, wrong version) all have the same cause: the wrong entry point file runs. They point in many wrong directions without this context
Files Affected
- package.json — "main" field must match the file containing actual Electron logic
- public/electron.js — if it exists, it overwrites build/electron.js on every CRA build; must stay in sync with intended entry point or be deleted
- dist/win-unpacked/resources/app.asar — the packaged bundle; inspecting its package.json is the fastest diagnostic
Permission Mode
Accept Edits was ON (auto-accepting changes)
Can You Reproduce This?
Yes, every time with the same prompt
Steps to Reproduce
_No response_
Claude Model
Sonnet
Relevant Conversation
---
Summary
When working on a CRA-based Electron app, Claude spent ~3 hours debugging why a packaged .exe was ignoring all new
code (wrong version shown, Electron menu visible, file dialogs doing nothing). The root cause was a one-line mismatch
in package.json. Claude never identified it directly — the fix was found by manually inspecting the ASAR bundle.
This is a common Electron+CRA project structure that many developers use. Claude has no base knowledge of how it
works, so it chases wrong theories instead of going straight to the real check.
---
The Stack
- Electron 29
- React 18 / Create React App (react-scripts 5)
- electron-builder 24
- Windows, NSIS installer target
---
How CRA + Electron packaging works (the part Claude doesn't know)
In a typical CRA-based Electron project:
1. CRA's npm run build copies everything in public/ to build/
2. If public/electron.js exists ? build/electron.js always exists after every build
3. electron-builder reads "main" from package.json and uses exactly that file as the Electron entry point — no
auto-detection, no override
The original CRA+Electron boilerplate uses:
"main": "build/electron.js"
...with the main process code in public/electron.js (which CRA copies to build/).
Many tutorials and developers later move the main process code to electron/main.js for cleaner organization, and
update "main": "electron/main.js" — but forget to delete or update public/electron.js.
Result: build/electron.js (the old boilerplate, with no Express, no menu hiding, no custom logic) silently runs in the
packaged app. The new electron/main.js is never executed. No error is thrown.
---
Symptoms in the packaged app
- Default Electron menu bar visible (because the old file never calls Menu.setApplicationMenu(null))
- File open dialogs do nothing (because the old file has no Express server / IPC handlers)
- Wrong version shown (because API calls to the local Express server fail — it was never started)
- App appears to load normally (the React UI renders fine from build/index.html)
These symptoms together point in many wrong directions: CORS, ASAR path issues, preload failures, port conflicts,
webSecurity settings. Claude explored all of them.
---
The actual fix
Check the ASAR bundle's package.json to see what "main" actually says at runtime:
node -e "
const asar = require('@electron/asar');
const pkg = asar.extractFile('dist/win-unpacked/resources/app.asar', 'package.json');
console.log(pkg.toString());
"
Then verify that the file "main" points to contains the actual current code — not old boilerplate.
Fix: "main" in package.json and the file containing your real Electron logic must always be the same file. If
public/electron.js exists and "main" points to build/electron.js, the code in public/electron.js is what runs.
---
What Claude should do instead
When debugging a packaged Electron app where new code seems to have no effect, Claude should immediately:
1. Inspect the ASAR package.json to confirm which file "main" points to at runtime
2. Extract and verify that file's content from the ASAR matches the expected current code
3. Check whether public/electron.js exists — if so, confirm it stays in sync with the intended entry point
This takes 30 seconds. Instead, Claude spent 3 hours on wrong theories.
---
Why this matters at scale
CRA + Electron is an extremely common beginner-to-intermediate stack. The public/electron.js ? electron/main.js
migration is a natural step that many developers take. The failure mode is completely silent. Claude having zero base
awareness of this pattern means every affected user fights it from scratch.
---
Feel free to copy as-is or trim. The ASAR inspection command at the end is the key thing — anyone searching for
"packaged Electron app ignoring new code" who finds this will have their answer in one command.
Impact
Critical - Data loss or corrupted project
Claude Code Version
2.1.75 (Claude Code)
Platform
Anthropic API
Additional Context
_No response_
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗