fix: port conflicts & syntax errors bringing down flask#36
Conversation
d4098b5 to
a0241f7
Compare
850e00e to
7f92a15
Compare
17d2fb1 to
6aecacc
Compare
Running `npm run start` while another instance is already running crashes because Flask (port 5000) and React (port 3000) use hardcoded ports. Flask has no built-in port conflict handling unlike react-scripts. Changes: - Flask auto-detects a free port via find_free_port() and writes it to .api-port. Keeps debug=True (unchanged) for hot reloading. - New setupProxy.js reads .api-port and proxies /api/* to Flask. - Frontend uses relative URLs instead of hardcoded http://127.0.0.1:5000. - Drop concurrently; run Flask in background and react-scripts in foreground so its built-in port conflict prompt works natively. https://claude.ai/code/session_017KPNZRmcaF3fPXMSiiQST1
6aecacc to
8807c35
Compare
|
I think this approach is a bit much for the problem. We could simply add an npm script like |
Werkzeug's reloader parent exits when the child crashes with a non-restart exit code, and nothing in start.sh brings it back. Wrap the pagination import in try/except so the child always starts, and pass extra_files so the file watcher monitors api/*.py even when an import fails. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
`os.environ.get("API_PORT", 5000)` returns "" when the key exists but
is empty, causing `int("")` to crash. Use `or` fallback instead.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
gjoseph92
left a comment
There was a problem hiding this comment.
I'm in favor of this approach. Asking people to kill random things on other ports is a bit inconsiderate.
When pagination.py has a syntax error, surface the traceback in a CRA-style error overlay in the frontend rather than silently showing "No projects found". Clears automatically on the next successful request. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit bff60bf. Configure here.
Change "Compiled with problems:" to "Server error:" since this overlay displays Python API errors, not JavaScript compilation failures. https://claude.ai/code/session_01CmiEo4xyYQJMR9LoxiqdFL
melicarls
left a comment
There was a problem hiding this comment.
I think this looks like a reasonable fix! Thank you so much for taking this on. Agreed that asking candidates to kill processes is poor form.
I'm admittedly not the most adept with startup scripts and port handling - @gjoseph92 , could you give another pass and second approval?
Instead of falling back to a random ephemeral port (e.g. 60736) when 5000 is taken, try ports sequentially from 5000-5019. Print the active port on startup and support API_PORT env var override for candidates who need to port-forward. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
ahh @gjoseph92 is out today/tomorrow so we probably shouldn't wait on him |
|
I haven't reviewed, but if Gabe was mostly happy with it and @melicarls you think it looks good, let's just merge and try it! We can post in eng-interviews to be on the lookout for issues |
|
As a last resort, if there are issues, can always have candidates check out the commit before, no worse than having to deal with a stuck server |



Motivation
Can't
npm run startwhile port 5000 is occupied because the Flask API uses hardcoded port 5000.Additionally, when a candidate introduces a syntax error in
pagination.py, the Werkzeug reloader parent process exits entirely (it only loops on exit code 3, and a SyntaxError during import causes exit code 1). Sincestart.shruns the API in the background, nothing restarts it -- the dev server dies and stays dead even after the error is fixed.Changes
Auto-detect a free API port with predictable fallback (
scripts/start.sh,package.json): Probes ports sequentially from 5000-5019 and passes the chosen one asAPI_PORT(for Flask) andREACT_APP_API_PORT(for the frontend). Prints the active port on startup and honors anAPI_PORT=<port> npm startoverride for special cases. Dropsconcurrently-- runs Flask in the background and react-scripts in the foreground so react-scripts built-in port conflict prompt works natively.Flask reads
API_PORT(api/app.py): Reads the port from the env var withorfallback to handle empty strings. Falls back to 5000 for standalone usage.Configurable API URL (
src/api/apiImpl.ts): Replaces hardcoded port 5000 with a URL built fromREACT_APP_API_PORT, defaulting to 5000.Survive syntax errors in candidate files (
api/app.py): Wraps thepaginationimport in try/except so a SyntaxError does not crash the Werkzeug reloader child process. Passesextra_filestoapp.run()so the file watcher monitorsapi/*.pyeven when an import fails (failed imports are not insys.modules, so Werkzeug would not otherwise notice the fix). Returns a clear 500 with the traceback when the import is broken.Surface API errors in a full-page overlay (
src/Projects.tsx,src/styles.css): When/api/projectsreturns an error, Projects renders a CRA-style full-page "Server error:" overlay with the traceback. Clears automatically on the next successful request.