Skip to content

fix: prevent app hang when server fails to start#342

Open
Akash504-ai wants to merge 2 commits into
AOSSIE-Org:mainfrom
Akash504-ai:fix/server-start-timeout
Open

fix: prevent app hang when server fails to start#342
Akash504-ai wants to merge 2 commits into
AOSSIE-Org:mainfrom
Akash504-ai:fix/server-start-timeout

Conversation

@Akash504-ai
Copy link
Copy Markdown

@Akash504-ai Akash504-ai commented Apr 30, 2026

Description

Fixes an issue where the app would hang indefinitely if the backend server failed to start.

  • Added timeout to server readiness check
  • Properly reject promise on failure
  • Handle startup errors to avoid silent freeze

Functional Verification

  • Verified app exits cleanly when server fails to start
  • Success case (normal startup) not fully verified in Electron runtime

Additional Notes

This change only affects Electron main process startup flow.

Summary by CodeRabbit

  • Bug Fixes
    • Added a 15-second timeout for server startup to prevent the application from hanging indefinitely if the server fails to start.
    • Improved error handling during app initialization with graceful shutdown when server startup fails.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

Warning

Rate limit exceeded

@Akash504-ai has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 51 minutes and 33 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d9f29e57-9fd1-448c-a8bf-28ca16be328c

📥 Commits

Reviewing files that changed from the base of the PR and between 126c4a2 and 97e0aa1.

📒 Files selected for processing (1)
  • electron/main.cjs

Walkthrough

The Electron main process adds timeout handling to server initialization. waitForServer now rejects after a configurable timeout (default 15 seconds) instead of retrying indefinitely. The app startup is wrapped in try/catch to log failures, terminate the server process, and gracefully exit if server startup fails.

Changes

Cohort / File(s) Summary
Server Startup Timeout & Error Handling
electron/main.cjs
Added configurable timeout to waitForServer (default 15s) with rejection on timeout. Updated startServer to handle rejection by logging, terminating spawned process, and propagating error. Wrapped Electron app startup in try/catch to log failures and call app.quit() on server startup failure.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

Typescript Lang

Poem

🐰 A server waits, but now with grace,
No endless loops in cyberspace!
Fifteen seconds, then we flee,
Timeout's caught with clarity. ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description addresses the main issue and documents the changes made, but is missing the required template sections like 'Addressed Issues' with issue number link and comprehensive functional verification checklist items. Add the issue number link in 'Addressed Issues' section and complete the functional verification checklist to match the repository template requirements.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: prevent app hang when server fails to start' clearly and concisely summarizes the main change: preventing an indefinite app hang by implementing server startup timeout handling.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 51 minutes and 33 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
electron/main.cjs (1)

53-80: ⚠️ Potential issue | 🔴 Critical

Add error and exit event listeners to the spawned process to prevent crashes and delayed failure detection.

The spawn() call lacks error and exit listeners. If spawning fails (e.g., 'node' command not found), the unhandled error event can crash the app. If the process exits before readiness checks pass, the error won't be caught until the 15-second timeout expires instead of failing immediately.

Suggested fix
 function startServer() {
   return new Promise((resolve, reject) => {
+    let settled = false;
+    const fail = (err) => {
+      if (settled) return;
+      settled = true;
+      if (serverProcess) serverProcess.kill();
+      reject(err);
+    };
+
     const serverPath = path.join(
       process.resourcesPath,
       'app.asar.unpacked',
       '.output',
       'server',
       'index.mjs'
     );

     console.log("Starting server from:", serverPath);

     serverProcess = spawn('node', [serverPath], {
       stdio: 'ignore',       // no terminal
       windowsHide: true,     // hide CMD
       env: {
         ...process.env,
         HOST: serverHost,
         PORT: serverPort.toString(),
       },
     });

+    serverProcess.once('error', (err) => {
+      fail(new Error(`Server process failed to spawn: ${err.message}`));
+    });
+
+    serverProcess.once('exit', (code, signal) => {
+      if (!settled) {
+        fail(new Error(`Server exited before readiness check passed (code=${code}, signal=${signal})`));
+      }
+    });
+
     waitForServer(`http://localhost:${serverPort}`)
       .then(resolve)
       .catch((err) => {
         console.error('Server failed to start:', err);
-        if (serverProcess) serverProcess.kill();
-        reject(err)
+        fail(err);
       });
   });
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@electron/main.cjs` around lines 53 - 80, The spawn() of the server
(serverProcess = spawn('node', [serverPath], ...)) needs immediate 'error' and
'exit' listeners so failures are detected and handled instead of crashing or
waiting for waitForServer timeout; add serverProcess.on('error', ...) to log the
error, kill/cleanup the process and reject the Promise (or call reject with the
error) and add serverProcess.on('exit', (code, signal) => ...) to log the
premature exit and reject the Promise immediately (also kill/cleanup if needed),
ensuring these handlers reference serverProcess, serverPath, serverHost/
serverPort for context and that waitForServer's pending promise is rejected when
the process fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@electron/main.cjs`:
- Around line 109-115: The catch block after await startServer()/createWindow()
must ensure any spawned backend is terminated: check the serverProcess variable
(from startServer) for existence and whether it's still running, call
serverProcess.kill() (prefer SIGTERM or appropriate signal) and optionally
wait/force-kill if it doesn't exit, then call app.quit(); update the catch in
the startup sequence handling to kill serverProcess before app.quit() so the
backend isn't orphaned.
- Around line 31-44: The waitForServer function can hang if an HTTP request
connects but never responds because the timeout is only checked in the 'error'
handler; update waitForServer to enforce a per-request timeout by capturing the
request object (e.g., const req = http.get(...)), call
req.setTimeout(timeoutPerAttempt) to trigger a timeout handler that aborts the
request and treats it like an error, and before each new attempt ensure the
overall deadline (Date.now() - start > timeout) is checked so you reject
promptly; changes should be applied inside waitForServer around the http.get
call and its handlers (use the same timeout logic currently used in the outer
error handler).

---

Outside diff comments:
In `@electron/main.cjs`:
- Around line 53-80: The spawn() of the server (serverProcess = spawn('node',
[serverPath], ...)) needs immediate 'error' and 'exit' listeners so failures are
detected and handled instead of crashing or waiting for waitForServer timeout;
add serverProcess.on('error', ...) to log the error, kill/cleanup the process
and reject the Promise (or call reject with the error) and add
serverProcess.on('exit', (code, signal) => ...) to log the premature exit and
reject the Promise immediately (also kill/cleanup if needed), ensuring these
handlers reference serverProcess, serverPath, serverHost/ serverPort for context
and that waitForServer's pending promise is rejected when the process fails.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 166dbf54-eb20-4f64-ae3b-4fa19782fc74

📥 Commits

Reviewing files that changed from the base of the PR and between c890fba and 126c4a2.

📒 Files selected for processing (1)
  • electron/main.cjs

Comment thread electron/main.cjs Outdated
Comment thread electron/main.cjs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant