Title: Claude loses hours debugging CRA + Electron packaged app when "main" field and entry point file are out of sync

Resolved 💬 3 comments Opened Mar 13, 2026 by yaiol Closed May 24, 2026

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_

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗