Skip to content

Commit e27ef5d

Browse files
fix(ports): handle startModelServer rejection on the promise, not a try/catch
SonarCloud reliability (C on new code): startModelServer became async (it scans for a free port), so a try/catch wrapped around a fire-and-forget call can't catch its rejection (index.ts:201). Handle it on the promise with .catch instead, matching the llm.init().catch pattern beside it. Applied the same to the other two fire-and-forget call sites (index.ts boot + ipc restart) so a rejected port scan is always logged, never an unhandled promise rejection.
1 parent d1cdb10 commit e27ef5d

2 files changed

Lines changed: 11 additions & 10 deletions

File tree

src/main/index.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,9 @@ app.whenReady().then(() => {
198198
/* ignore */
199199
}
200200
}
201-
try {
202-
void startModelServer()
203-
} catch (e) {
204-
console.error('[gateway] start failed', e)
205-
}
201+
// startModelServer is async (it scans for a free port); a try/catch can't catch its rejection,
202+
// so handle it on the promise itself.
203+
startModelServer().catch((e) => console.error('[gateway] start failed', e))
206204
void import('./llm').then(({ llm }) =>
207205
llm.init().catch((err) => console.error('[gateway] LLM init failed', err))
208206
)
@@ -329,7 +327,9 @@ app.whenReady().then(() => {
329327
setupIPC()
330328
setupRagIPC()
331329
setupMcpIpc() // basic MCP connectors (management + chat tool extension)
332-
void startModelServer() // one OpenAI-compatible local gateway (LLM + STT); auto-picks a free port
330+
// one OpenAI-compatible local gateway (LLM + STT); auto-picks a free port. Async, so handle a
331+
// rejection on the promise (a try/catch around a fire-and-forget async call can't catch it).
332+
startModelServer().catch((e) => console.error('[model-server] start failed', e))
333333
startMediaServer() // loopback HTTP for seekable local media (meeting videos)
334334
// Heal a stale active-model.json whose model gained a vision projector after it was
335335
// activated (e.g. Gemma 4 E2B) — turns vision on at launch if the projector is now

src/main/ipc.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,7 +1652,9 @@ export function setupIPC() {
16521652
} catch {
16531653
/* not running */
16541654
}
1655-
void startModelServer() // re-listens; falls back to a free port if the preferred one is held
1655+
// re-listens; falls back to a free port if the preferred one is held. Async, so catch a
1656+
// rejection on the promise rather than leaving it unhandled.
1657+
startModelServer().catch((e) => console.error('[model-server] restart failed', e))
16561658
return { success: true }
16571659
}
16581660
return { success: false, error: `cannot restart "${id}"` }
@@ -1984,9 +1986,8 @@ export function setupIPC() {
19841986
// Which STT engine + model would run right now (provenance) + the installed transcription
19851987
// models a picker can switch to (via the existing models:set-active-modal — this only lists).
19861988
ipcMain.handle('transcription:active-info', async () => {
1987-
const { getActiveTranscriptionInfo, transcriptionModelOptions } = await import(
1988-
'./transcription/select'
1989-
)
1989+
const { getActiveTranscriptionInfo, transcriptionModelOptions } =
1990+
await import('./transcription/select')
19901991
const { listInstalled } = await import('./models-manager')
19911992
const { modelsByKind } = await import('@offgrid/models')
19921993
const info = getActiveTranscriptionInfo()

0 commit comments

Comments
 (0)