Cursor Debug Browser Leaves Stale Flask Process, Breaks Unicode Responses

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Summary: In Cursor on Windows, launching our Flask app through the built-in Run/Debug browser starts the server under debugpy. Even after closing Cursor, that debugpy process keeps port 5000 open. When I restarted Cursor, the port was still busy so the new Flask instance routed through the lingering debugpy proxy. That proxy wasn’t handling UTF-8 correctly, so any API response containing an emoji triggered ‘charmap’ codec can’t encode character … and the server stopped responding.
What I observed:
Using Cursor’s internal browser to start Flask (port 5000) leaves a background process running even after Cursor closes.
netstat -ano showed the same PID holding 127.0.0.1:5000 with CLOSE_WAIT connections; only killing that PID freed the port.
While the stale process was around, hitting the server via curl or the app produced the Unicode error and responses hung indefinitely.
Workaround: Manually terminate the old PID (Stop-Process -Id ), then start Flask from a regular terminal (python app.py). No more Unicode issues once the server runs outside the lingering debugpy instance.
Request: Please ensure Cursor’s internal browser/debug runner shuts down cleanly and releases sockets when the IDE closes, and/or provide a way to disable the auto-run behavior for web apps.

Steps to Reproduce

Steps to reproduce (Windows, Cursor 2025.14.x):
Open any Flask app inside Cursor.
Launch it via Cursor’s internal Run/Debug browser (the embedded web view) so the server starts on port 5000 under debugpy.
Close Cursor without stopping the server first.
Reopen Cursor and try to run the app again; the initial debugpy process still owns 127.0.0.1:5000.
Send a request that makes the Flask app return an emoji (e.g., a response containing :chart_increasing:).
The response fails with UnicodeEncodeError: ‘charmap’ codec can’t encode character… and the request hangs until you terminate the stale PID.

Operating System

Windows 10/11

Current Cursor Version (Menu → About Cursor → Copy)

Version: 2.0.40 (user setup)
VSCode Version: 1.99.3
Commit: a9b73428ca6aeb2d24623da2841a271543735560
Date: 2025-10-30T04:12:35.564Z
Electron: 34.5.8
Chromium: 132.0.6834.210
Node.js: 20.19.1
V8: 13.2.152.41-electron.0
OS: Windows_NT x64 10.0.26200

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hey, thanks for the report. This looks like a real issue with process cleanup in Cursor’s debug runner.

I’ll pass this to the team. The debugpy process should shut down cleanly when Cursor closes, and the Unicode issue suggests the debug proxy may be missing proper UTF‑8 handling.

In the meantime, your workaround is solid:

  • Kill the stale process: Stop-Process -Id <PID>
  • Run Flask directly: python app.py
  • Also try explicitly stopping the debug session (red square in the debug toolbar) before closing Cursor, this may help with cleanup

Also could you update to the latest version and let me know if the issue still persists?

Thanks for the detailed repro steps.

Bug is still occurring, details below:

Summary
A Flask dev server started from Cursor continues running even after sending Ctrl+C or closing the terminal tab. Only an external taskkill terminates it, suggesting Cursor’s embedded browser or background plumbing keeps the socket open.

Environment

  • Version: 2.0.43 (user setup)
  • VSCode Version: 1.99.3
  • Commit: 8e4da76ad196925accaa169efcae28c45454cce0
  • Date: 2025-10-30T18:49:27.589Z
  • Electron: 34.5.8
  • Chromium: 132.0.6834.210
  • Node.js: 20.19.1
  • V8: 13.2.152.41-electron.0
  • OS: Windows_NT x64 10.0.26200
  • Project: standard Flask app (python app.py), listening on 127.0.0.1:5000

Steps to Reproduce

  1. In Cursor’s terminal, run the Flask app (e.g. .\\venv\\Scripts\\python.exe app.py or python app.py).
  2. Open http://127.0.0.1:5000/ in Cursor’s built-in browser (or the “Preview” panel).
  3. Try to stop the server:
    • Press Ctrl+C in the original terminal.
    • Close the terminal tab (the one that started Flask).
  4. Inspect listening sockets: netstat -ano | findstr :5000.

Expected Result
After Ctrl+C or closing the terminal, PID for python.exe should exit and port 5000 should be freed.

Actual Result
The Flask process keeps listening on port 5000 (TCP LISTENING), even though the terminal tab is gone. Closing the terminal does not stop it. Only taskkill /PID <pid> /F or similar external action releases the port.

Observations

  • The problem is reproducible even when Ctrl+C prints the usual Flask shutdown message.
  • When Cursor’s internal browser is open on the app page, it appears to keep a connection alive; this may prevent the process from receiving/handling the interrupt cleanly.
  • The PID remains visible in netstat and cannot be found via tasklist immediately after a taskkill, suggesting Cursor might relaunched or reattached automatically.
  • Restarting Cursor clears the lock, indicating it comes from the editor runtime rather than the Flask code.

Workaround
After shutting down the terminal:

netstat -ano | findstr :5000
taskkill /PID <pid> /F

Suggested Fix
Ensure terminals tied to background processes send a proactive SIGINT/CTRL_BREAK and close any embedded-browser sockets. Alternatively, prompt the user that a background process is still running and offer an explicit “Terminate” dialog.

Later edit:
I have to reboot the PC because port 5000 is non-responsive. Report below:

  1. Port status: netstat still shows 127.0.0.1:5000 held by PID 29936, but that PID no longer maps to any visible process (tasklist, Get-Process, WMIC all return “not found”).
  2. Likely cause: a zombie socket owned by a system-level helper (or a kernel driver) that doesn’t surface in non-elevated tools—possibly Cursor’s embedded browser keeping the listener alive.
  3. Next steps:
    • Re-run the editor (or reboot if convenient) to clear the stranded listener.
    • If you want to dig deeper before rebooting, run an elevated PowerShell and try Get-Process -Id 29936 -IncludeUserName or use Sysinternals handle.exe to identify the owner.
  4. Until the listener is cleared, binding to port 5000 continues to fail.