Cursor immediately exits on macOS after window becomes ready; ENOPRO appears during shutdown

Cursor immediately exits on macOS after window becomes ready; ENOPRO appears during shutdown

I’m experiencing an issue on macOS where Cursor launches its main process and successfully creates a window, but then immediately enters the Electron shutdown lifecycle and exits.

The issue was first noticed on September 29, 2026. Cursor was working normally on September 28, 2026.

I initially suspected that the ENOPRO error involving storage.json was causing the termination. However, after further testing, I now suspect that ENOPRO may actually be a secondary error that occurs during shutdown rather than the original trigger.

Environment

  • OS: macOS 26.5 (Build 25F71)

  • CPU: Apple M4 Pro

  • RAM: 24 GB

  • Architecture: Apple Silicon (darwin-arm64)

  • Cursor version observed while working normally on September 28: 3.21.18

  • Cursor version after the update: 3.22.12

  • Current version after rollback: 3.21.18

  • Electron: 42.10.0

  • Chrome: 148.0.7778.280

Cursor was working normally on September 28, 2026.

From /var/log/install.log, I found multiple Cursor processes running on September 28 with:

--annotation=_productName=Cursor
--annotation=_version=3.21.18

At some point afterwards, Cursor was updated to 3.22.12.

I did not manually approve an update.

The issue was first noticed on September 29, 2026. Although the problem was first noticed after the update, reinstalling 3.21.18 does not resolve it, so I cannot currently determine whether the update caused the problem or whether the update merely coincided with another system-level change.

Initial error

Launching Cursor produces:

Q9 [CodeExpectedError]: ENOPRO: No file system provider found for resource
'file:///Users/<username>/Library/Application Support/Cursor/User/globalStorage/storage.json'

The stack trace includes:

yu.withProvider
yu.withWriteProvider
yu.writeFile
N8.doSave

On one launch I also observed:

libc++abi: terminating due to uncaught exception of type Napi::Error
zsh: abort

storage.json itself exists

I checked the file and directory permissions.

The relevant files/directories look like:

-rw-r--r--@ ... storage.json
drwxr-xr-x@ ... globalStorage
drwxr-xr-x@ ... User
drwx------@ ... Cursor

The file exists, is valid JSON, and is owned by my user account.

So this does not appear to be simply a missing storage.json or an obvious filesystem permission problem.

The issue also occurs with completely fresh user data

I moved the original Cursor application data directory out of the way:

mv "$HOME/Library/Application Support/Cursor" \
   "$HOME/Library/Application Support/Cursor.backup-20260929"

I then launched Cursor again so that it would create a completely fresh user-data directory.

The same termination behavior occurred.

I also tested with an explicitly isolated temporary user-data directory:

/Applications/Cursor.app/Contents/MacOS/Cursor \
  --user-data-dir=/tmp/cursor-final-test \
  --disable-extensions \
  --disable-gpu \
  --skip-welcome \
  --verbose

The application still exited.

Importantly, the ENOPRO error was then reported against the newly created temporary directory:

/tmp/cursor-final-test/User/globalStorage/storage.json

This makes it unlikely that the original globalStorage contents alone are responsible.

Additional isolation tests

I have also tested:

  • --disable-extensions → same behavior

  • --disable-gpu → same behavior

  • completely fresh --user-data-dir → same behavior

  • fresh Classic mode (--classic) → same behavior

  • default/Glass mode → same behavior

  • a clean environment using env -i → same behavior

  • moving the original globalStorage out of the way → same behavior

  • reinstalling Cursor 3.21.18 → same behavior

I also checked:

~/Library/Logs/DiagnosticReports

and did not find a recent Cursor/Electron crash report corresponding to this issue.

Important observation: ENOPRO may be a secondary shutdown error

After further investigation, I found that Cursor does not appear to crash immediately at the native process level.

In a fresh Classic-mode test, the log contains:

window#load: attempt to load window (id: 1)

followed by:

window#load: window reported ready (id: 1)

So the BrowserWindow successfully reaches the ready state.

Shortly afterwards, the application enters the normal Electron shutdown lifecycle:

Lifecycle#app.on(before-quit)
Lifecycle#window.on('close')
Lifecycle#window.on('closed')
Lifecycle#app.on(window-all-closed)
Lifecycle#app.on(will-quit)

The relevant sequence is approximately:

window#load: window reported ready (id: 1)
        ↓
Lifecycle#app.on(before-quit)
        ↓
Lifecycle#window.on('close')
        ↓
Lifecycle#window.on('closed')
        ↓
Lifecycle#app.on(window-all-closed)
        ↓
Lifecycle#app.on(will-quit)

The ENOPRO error appears during the shutdown sequence, after:

StorageMainService: closed application storage

and then:

Q9 [CodeExpectedError]: ENOPRO: No file system provider found for resource
'file:///tmp/cursor-final-test/User/globalStorage/storage.json'

Therefore, my current hypothesis is that the ENOPRO may be a secondary error during shutdown, rather than the original trigger that causes Cursor to exit.

I would particularly like to understand what is causing the first:

Lifecycle#app.on(before-quit)

event.

Classic mode vs. default mode

I also tested Cursor with:

--classic

and without it.

Both modes eventually terminate after the window becomes ready.

Therefore, the issue does not appear to be specific to the Glass/default UI mode.

Process behavior

During startup, Cursor successfully creates several child processes, including processes corresponding to:

  • file watcher

  • extension host

  • pty host

  • MCP process

  • conversation search

The main process remains alive long enough for the BrowserWindow to become ready, and then the application enters its shutdown lifecycle.

In several clean tests, the final process exit code was:

0

This makes me suspect that, in those cases, the application may be intentionally entering Electron’s quit lifecycle rather than simply crashing.

I also had one earlier test that ended with exit code:

143

which corresponds to termination by SIGTERM at the shell exit-code level. However, I have not identified what sent the signal, so I do not want to assume that this was the root cause.

macOS unified logs

I also inspected macOS unified logs around the termination.

They show Cursor-related process termination and some sandbox/security-related messages, including denials involving system services.

However, I have not found evidence proving that those sandbox messages are the cause of the termination, so I don’t want to overstate this part.

What I am trying to determine

At this point, I am trying to determine whether this is:

  1. a Cursor/Electron regression,

  2. a macOS filesystem/provider issue,

  3. a code-signing or sandbox/security issue,

  4. another system-level condition causing Cursor to call app.quit(),

  5. or something else in Cursor’s startup/lifecycle handling.

The fact that the issue occurs with:

  • both Cursor 3.22.12 and 3.21.18,

  • a completely fresh user-data directory,

  • extensions disabled,

  • GPU disabled,

  • Classic mode,

  • default/Glass mode,

  • and a clean environment

makes me suspect that the root cause may be outside the normal Cursor user-data state.

Question

Could someone from the Cursor team suggest the next diagnostic step to identify what is triggering the first before-quit event?

In particular, I would like to determine whether there is a known condition in Cursor/Electron that can cause the application to:

create BrowserWindow
→ report window ready
→ enter before-quit
→ close the window
→ quit

while subsequently producing:

ENOPRO: No file system provider found

during storage shutdown.

I can provide:

  • the complete Cursor startup logs,

  • the complete --verbose logs,

  • macOS unified logs,

  • diagnostic reports,

  • process information,

  • and any other information needed for further investigation.

Thanks for any suggestions on the next diagnostic step.

Hey @Paulnia_Liu, you’ve got it right: the ENOPRO … storage.json is a shutdown side effect, not the trigger. And the quit pattern you’re seeing (a before-quit with no Lifecycle#quit() - begin in front of it, exit 0, once 143/SIGTERM) is the signature of something outside the app asking Cursor to quit, rather than Cursor quitting itself. That it survives rollback, a fresh --user-data-dir, extensions and GPU off, both modes, and env -i all points the same way.

To find the trigger:

  1. In your --verbose log, check whether Lifecycle#quit() - begin appears before the first before-quit. Absent = external quit (the expected finding); present = Cursor-side, and I’d want that log.
  2. Find the sender: give Terminal Full Disk Access, run sudo eslogger signal exit > ~/Desktop/sig.json, launch Cursor, Ctrl+C once it closes, then search sig.json for Cursor.
  3. Rule out macOS terminators: Screen Time (App Limits/Downtime), MDM/config profiles (System Settings > General > Device Management) if it’s a work Mac, and any recently added security/EDR or automation tools.
  4. Launch in a brand-new macOS user account: if it stays open, the trigger is in your account’s setup; if not, it’s system-wide.

Step 2 should name the culprit. If step 1 shows the Lifecycle#quit() line, reply with that log and I’ll take it from our side.

Hi, thanks for the detailed guidance.

I completed Step 1. In the --verbose log, I found:

Lifecycle#app.on(before-quit)

but there is no Lifecycle#quit() - begin before it. So this appears to match the external-quit pattern you described.

For Step 2, I also ran the signal/exit audit. I found a potentially relevant corporate security service that appears to have process-management functionality and a policy containing Cursor in its macOS process block list. The audit log also shows this service being associated with a killall/SIGTERM targeting Cursor.

Since this is a company-managed security service, I don’t want to make any changes or disable anything before confirming it with our security/IT team. I’ll investigate this part further with them to verify whether it is actually responsible for the quit event.

Thanks again for pointing me in the right direction. The before-quit finding was especially helpful in narrowing this down.