Skip to content

fix(host-service): surface breaking failures instead of swallowing them - #5493

Merged
Kitenite merged 5 commits into
mainfrom
host-service-direct-run
Jul 8, 2026
Merged

Kitenite merged 5 commits into
mainfrom
host-service-direct-run

Conversation

@Kitenite

@Kitenite Kitenite commented Jul 7, 2026 •

Copy link
Copy Markdown
Member

Problem

Breaking host-service failures never reached the user. The confirmed 1.12.0 crash is the canonical case: a migration fails, the failure is swallowed, and the service limps on a half-migrated DB — then fails later in a confusing, unrelated way. Failures were being swallowed at multiple layers with no loud surface.

What changed

Three targeted fixes, each un-swallowing a breaking failure (legitimate best-effort catches — teardown, fan-out guards, optional features — were deliberately left alone):

  1. db.ts — migration throws. Removed the try/catch that logged-and-continued around migrate(), so a failed migration crashes the child at startup (before the safety net is installed → main().catch → exit(1)) with the real stack, instead of returning a half-migrated DB. Also added busy_timeout = 5000.

  2. host-service-coordinator.ts — alert on child crash. When a running child dies unexpectedly, the coordinator now shows a native dialog ("Host service crashed" with exit code/signal) and a Restart button, rather than only emitting a passive stopped status event nothing reacts to. Deliberate stop()/quit set status to stopped first, so they return early and never alert; startup-phase deaths are surfaced by (3), so no double-alert.

  3. LocalHostServiceProvider.tsx — surface start failures. The fire-and-forget start mutation now has an onError that logs + toasts the failure instead of dropping the rejection into unread React Query state (auth-token preconditions filtered to avoid startup-race noise).

Deliberately out of scope

  • Not moving host-service in-process (keeps crash isolation / clean reset() / per-org separation).
  • Not changing the process safety net to exit() on every uncaught error — crashing the whole session-supervisor on a stray post-startup throw, with no auto-restart, is worse than logging it.

Verification

  • Typecheck (desktop + host-service): clean. Lint: clean. host-service createDb tests pass.
  • The native crash dialog fires only on a real child crash; not yet driven end-to-end in the running app.

Open in Stage

Summary by cubic

Stop swallowing breaking host-service failures and surface them clearly to users. Failed migrations now crash early, crashes show a native error dialog, and start errors show a toast.

  • Bug Fixes
    • packages/host-service/src/db/db.ts: Let failed migrations throw instead of returning a half‑migrated DB; set busy_timeout = 5000.
    • apps/desktop/src/main/lib/host-service-coordinator.ts: Show a native “Host service crashed” error box with exit code/signal on unexpected exits; emit the real previous status; alert only for crashes of running children; recovery via tray menu Restart.
    • apps/desktop/src/renderer/.../LocalHostServiceProvider.tsx: Add onError to the start mutation to log and toast failures; ignore typed UNAUTHORIZED auth‑token preconditions.
    • apps/desktop/src/lib/trpc/routers/host-service-coordinator: Throw TRPCError with code UNAUTHORIZED when no auth token is present so the renderer can reliably filter expected preconditions.

Written for commit c0b68b4. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added a native error dialog when the host service stops unexpectedly, informing users that workspaces/terminals are unavailable until restart.
    • Added clearer UI feedback when the host service fails to start (toast notification on other errors).
  • Bug Fixes
    • Improved detection and handling of unexpected host-service exits, keeping availability/status consistent.
    • Improved unauthorized-start behavior by suppressing start error notifications when the user isn’t authenticated.
  • Bug Fixes / Reliability
    • Improved database startup reliability with a SQLite busy timeout and safer migration behavior to avoid half-migrated states.

- db.ts: let a failed migration throw instead of returning a half-migrated DB; add busy_timeout
- coordinator: alert (native dialog + Restart) when a running host-service child crashes, instead of only emitting a status event
- renderer: surface start-mutation failures via onError instead of dropping them into unread state
@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@ghost

ghost commented Jul 7, 2026 •

Copy link
Copy Markdown

Ready to review this PR? Stage has broken it down into 4 individual chapters for you:

Title
1 Prevent silent database migration failures
2 Improve error reporting in the coordinator router
3 Alert users on unexpected host service crashes
4 Surface startup failures in the UI
Open in Stage

Chapters generated by Stage for commit c0b68b4 on Jul 8, 2026 6:52pm UTC.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Host-service crash handling now shows a native error dialog after unexpected child exits, start failures now surface as unauthorized TRPC errors or renderer toasts, and database initialization now sets a busy timeout and throws on migration failure.

Changes

Desktop host-service error handling

Layer / File(s) Summary
Crash detection and native alert
apps/desktop/src/main/lib/host-service-coordinator.ts
The child exit handler now records code and signal, clears state on unexpected exits, emits stopped status from the prior state, and calls a new crash-alert method when the prior state was running. The new method logs the crash cause and shows an Electron error dialog.
Structured start errors and toast
apps/desktop/src/lib/trpc/routers/host-service-coordinator/index.ts, apps/desktop/src/renderer/routes/_authenticated/providers/LocalHostServiceProvider/LocalHostServiceProvider.tsx
The router now throws UNAUTHORIZED TRPC errors when no auth token is available, and the renderer start mutation now logs failures, suppresses auth-token toasts, and shows a toast for other start errors.

Host-service database initialization

Layer / File(s) Summary
Busy timeout and migration failure
packages/host-service/src/db/db.ts
SQLite initialization now sets busy_timeout = 5000, and migration now throws on failure instead of returning a partially migrated database.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Title check ✅ Passed The title is concise and accurately summarizes the main change: surfacing breaking host-service failures.
Description check ✅ Passed The description covers the problem, changes, out-of-scope items, and verification, with only a few template sections left unfilled.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch host-service-direct-run

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

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/desktop/src/main/lib/host-service-coordinator.ts (1)

543-551: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Restart click can silently no-op when no auth token is present.

If loadToken() returns no token, the handler returns without any feedback, so the user who explicitly chose "Restart" sees nothing happen. Consider surfacing a follow-up dialog (or logging + re-alerting) so the failed precondition isn't invisible.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/main/lib/host-service-coordinator.ts` around lines 543 -
551, The restart flow in host-service-coordinator’s prompt handler can silently
exit after loadToken() returns no token, leaving the user with no feedback.
Update the .then(async ({ response }) => { ... }) path to handle the
missing-token branch explicitly by showing a follow-up dialog or
re-alerting/logging before returning, so the Restart action in this flow is
never an invisible no-op.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/desktop/src/main/lib/host-service-coordinator.ts`:
- Around line 414-425: The status transition in host-service-coordinator.ts is
using a hard-coded previous status of "running" when calling emitStatus, but
current.status can still be "starting" in this exit path. Update the logic
around the current.status check and the emitStatus call in
HostServiceCoordinator so it preserves the actual prior state and passes that
value instead of always "running", using the existing current.status/ crashed
flow to locate the fix.

---

Nitpick comments:
In `@apps/desktop/src/main/lib/host-service-coordinator.ts`:
- Around line 543-551: The restart flow in host-service-coordinator’s prompt
handler can silently exit after loadToken() returns no token, leaving the user
with no feedback. Update the .then(async ({ response }) => { ... }) path to
handle the missing-token branch explicitly by showing a follow-up dialog or
re-alerting/logging before returning, so the Restart action in this flow is
never an invisible no-op.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 45694c8a-89af-4b72-a731-32e29e60edd5

📥 Commits

Reviewing files that changed from the base of the PR and between baf5d15 and 9d73fe9.

📒 Files selected for processing (3)
  • apps/desktop/src/main/lib/host-service-coordinator.ts
  • apps/desktop/src/renderer/routes/_authenticated/providers/LocalHostServiceProvider/LocalHostServiceProvider.tsx
  • packages/host-service/src/db/db.ts

@greptile-apps

greptile-apps Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR un-swallows breaking host-service failures at three distinct layers: migration errors now crash the child process loudly instead of returning a half-migrated DB, unexpected crashes of a running child surface via a native dialog with a Restart button, and renderer-side start failures fire a toast instead of silently settling into unread React Query state.

  • db.ts: Removes the migration try/catch and adds busy_timeout = 5000 — clean and correct; the safety net at the process level (main().catch → exit(1)) ensures the crash propagates properly.
  • host-service-coordinator.ts: Adds alertChildCrashed which shows a native dialog.showMessageBox (Restart/Dismiss) only for deaths in \"running\" state; startup deaths continue to surface via the rejected start promise. The dialog is shown without a parent BrowserWindow, and restart failures after the user clicks "Restart" are only written to electron-log with no user-visible feedback.
  • LocalHostServiceProvider.tsx: Adds onError to the start mutation; auth-startup-race errors are suppressed by a substring match on \"auth token\", which is a fragile heuristic.

Confidence Score: 4/5

Safe to merge — all three changes move in the right direction and the core crash-surfacing logic is sound.

The migration-throw change in db.ts is clean and correct. The crash dialog logic correctly distinguishes running-state deaths from startup deaths, and the stop() guard prevents false dialogs on deliberate shutdown. Two gaps remain in the coordinator: the dialog is shown without a parent window (can appear behind the app on Windows), and if the user clicks Restart and the restart fails, the error is only written to electron-log with no user-visible feedback. The auth-error substring filter in the renderer is fragile but functional for the current error message shape.

apps/desktop/src/main/lib/host-service-coordinator.ts — the crash dialog UX and its restart error handling are the areas most likely to need a follow-up.

Important Files Changed

Filename Overview
apps/desktop/src/main/lib/host-service-coordinator.ts Adds crash detection and native dialog (Restart/Dismiss) when a running child exits unexpectedly; restart failures after user clicks Restart are only logged to electron-log with no user-facing feedback, and the dialog is shown without a parent BrowserWindow reference.
apps/desktop/src/renderer/routes/_authenticated/providers/LocalHostServiceProvider/LocalHostServiceProvider.tsx Adds onError handler to the start mutation to surface failures as toasts; auth-error suppression relies on a fragile substring check rather than a typed error code.
packages/host-service/src/db/db.ts Removes the migration try/catch so failures crash the child loudly, and adds busy_timeout = 5000 pragma for concurrent-access safety — both straightforward and correct changes.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant R as Renderer (LocalHostServiceProvider)
    participant M as Main (HostServiceCoordinator)
    participant C as Child (host-service)
    participant DB as SQLite DB

    R->>M: start mutation
    M->>C: spawn child process
    C->>DB: createDb() - migrate()
    alt migration fails (NEW: throws instead of swallow)
        DB-->>C: throws
        C-->>M: exit(1)
        M-->>R: onError - toast.error (NEW)
    else migration succeeds
        DB-->>C: ok
        C-->>M: health check passes
        M-->>R: Connection port+secret
        Note over C,M: service running
        alt child crashes unexpectedly (NEW)
            C-->>M: "exit event status=running"
            M->>M: alertChildCrashed()
            M-->>R: native dialog Host service crashed
            alt user clicks Restart
                M->>M: loadToken()
                M->>C: restart - spawn new child
            else user clicks Dismiss
                Note over M: stopped, no restart
            end
        end
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant R as Renderer (LocalHostServiceProvider)
    participant M as Main (HostServiceCoordinator)
    participant C as Child (host-service)
    participant DB as SQLite DB

    R->>M: start mutation
    M->>C: spawn child process
    C->>DB: createDb() - migrate()
    alt migration fails (NEW: throws instead of swallow)
        DB-->>C: throws
        C-->>M: exit(1)
        M-->>R: onError - toast.error (NEW)
    else migration succeeds
        DB-->>C: ok
        C-->>M: health check passes
        M-->>R: Connection port+secret
        Note over C,M: service running
        alt child crashes unexpectedly (NEW)
            C-->>M: "exit event status=running"
            M->>M: alertChildCrashed()
            M-->>R: native dialog Host service crashed
            alt user clicks Restart
                M->>M: loadToken()
                M->>C: restart - spawn new child
            else user clicks Dismiss
                Note over M: stopped, no restart
            end
        end
    end
Loading
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
apps/desktop/src/main/lib/host-service-coordinator.ts:533-557
**Dialog shown without parent window**

`dialog.showMessageBox` is called without a `BrowserWindow` argument. On Windows this causes the dialog to appear as a standalone system window that can easily be obscured behind the focused app window, leading users to believe the Restart button does nothing. On macOS the behavior is acceptable but still suboptimal. Passing the focused (or any visible) `BrowserWindow` pins the dialog to the front of the app's window stack.

Consider using `BrowserWindow.getFocusedWindow() ?? BrowserWindow.getAllWindows()[0]` as the first argument to `dialog.showMessageBox`.

### Issue 2 of 3
apps/desktop/src/main/lib/host-service-coordinator.ts:543-557
**Silent restart failure after user clicks "Restart"**

When `this.restart()` throws (e.g., the newly spawned child fails its health check), the error is swallowed in the `.catch()` and only written to `electron-log`. The user clicked "Restart", the dialog closes, but the service never comes up and no feedback is given. The `onError` toast in `LocalHostServiceProvider` only fires for mutations triggered from the renderer; this restart originates in the main process and bypasses that path entirely.

Consider calling `dialog.showErrorBox` or a second `dialog.showMessageBox` inside the `.catch` to tell the user that the restart itself failed.

### Issue 3 of 3
apps/desktop/src/renderer/routes/_authenticated/providers/LocalHostServiceProvider/LocalHostServiceProvider.tsx:44-45
**Fragile string-match auth-error filter**

The filter `error.message.toLowerCase().includes("auth token")` is a plain substring match. If the error message wording changes (e.g., "missing token", "invalid token", "no token available"), real startup-race noise slips through as a spurious toast. Conversely, any genuine failure whose message happens to contain "auth token" (e.g., "Failed to exchange auth token with upstream") is silently suppressed. A typed error code or a dedicated `TRPCClientError` subtype would make the boundary explicit and rename-proof.

Reviews (1): Last reviewed commit: "fix(host-service): surface breaking fail..." | Re-trigger Greptile

Comment on lines +533 to +557
void dialog
.showMessageBox({
type: "error",
title: "Host service crashed",
message: "The Superset host service stopped unexpectedly.",
detail: `Workspaces and terminals for this organization are unavailable until it restarts (${cause}).`,
buttons: ["Restart", "Dismiss"],
defaultId: 0,
cancelId: 1,
})
.then(async ({ response }) => {
if (response !== 0) return;
const { token } = await loadToken();
if (!token) return;
await this.restart(organizationId, {
authToken: token,
cloudApiUrl: mainEnv.NEXT_PUBLIC_API_URL,
});
})
.catch((error) => {
log.error(
`[host-service:${organizationId}] crash-alert restart failed:`,
error,
);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Dialog shown without parent window

dialog.showMessageBox is called without a BrowserWindow argument. On Windows this causes the dialog to appear as a standalone system window that can easily be obscured behind the focused app window, leading users to believe the Restart button does nothing. On macOS the behavior is acceptable but still suboptimal. Passing the focused (or any visible) BrowserWindow pins the dialog to the front of the app's window stack.

Consider using BrowserWindow.getFocusedWindow() ?? BrowserWindow.getAllWindows()[0] as the first argument to dialog.showMessageBox.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/main/lib/host-service-coordinator.ts
Line: 533-557

Comment:
**Dialog shown without parent window**

`dialog.showMessageBox` is called without a `BrowserWindow` argument. On Windows this causes the dialog to appear as a standalone system window that can easily be obscured behind the focused app window, leading users to believe the Restart button does nothing. On macOS the behavior is acceptable but still suboptimal. Passing the focused (or any visible) `BrowserWindow` pins the dialog to the front of the app's window stack.

Consider using `BrowserWindow.getFocusedWindow() ?? BrowserWindow.getAllWindows()[0]` as the first argument to `dialog.showMessageBox`.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +543 to +557
.then(async ({ response }) => {
if (response !== 0) return;
const { token } = await loadToken();
if (!token) return;
await this.restart(organizationId, {
authToken: token,
cloudApiUrl: mainEnv.NEXT_PUBLIC_API_URL,
});
})
.catch((error) => {
log.error(
`[host-service:${organizationId}] crash-alert restart failed:`,
error,
);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Silent restart failure after user clicks "Restart"

When this.restart() throws (e.g., the newly spawned child fails its health check), the error is swallowed in the .catch() and only written to electron-log. The user clicked "Restart", the dialog closes, but the service never comes up and no feedback is given. The onError toast in LocalHostServiceProvider only fires for mutations triggered from the renderer; this restart originates in the main process and bypasses that path entirely.

Consider calling dialog.showErrorBox or a second dialog.showMessageBox inside the .catch to tell the user that the restart itself failed.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/main/lib/host-service-coordinator.ts
Line: 543-557

Comment:
**Silent restart failure after user clicks "Restart"**

When `this.restart()` throws (e.g., the newly spawned child fails its health check), the error is swallowed in the `.catch()` and only written to `electron-log`. The user clicked "Restart", the dialog closes, but the service never comes up and no feedback is given. The `onError` toast in `LocalHostServiceProvider` only fires for mutations triggered from the renderer; this restart originates in the main process and bypasses that path entirely.

Consider calling `dialog.showErrorBox` or a second `dialog.showMessageBox` inside the `.catch` to tell the user that the restart itself failed.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +44 to +45
// Auth preconditions resolve once the token lands; not a real failure.
if (error.message.toLowerCase().includes("auth token")) return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Fragile string-match auth-error filter

The filter error.message.toLowerCase().includes("auth token") is a plain substring match. If the error message wording changes (e.g., "missing token", "invalid token", "no token available"), real startup-race noise slips through as a spurious toast. Conversely, any genuine failure whose message happens to contain "auth token" (e.g., "Failed to exchange auth token with upstream") is silently suppressed. A typed error code or a dedicated TRPCClientError subtype would make the boundary explicit and rename-proof.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/providers/LocalHostServiceProvider/LocalHostServiceProvider.tsx
Line: 44-45

Comment:
**Fragile string-match auth-error filter**

The filter `error.message.toLowerCase().includes("auth token")` is a plain substring match. If the error message wording changes (e.g., "missing token", "invalid token", "no token available"), real startup-race noise slips through as a spurious toast. Conversely, any genuine failure whose message happens to contain "auth token" (e.g., "Failed to exchange auth token with upstream") is silently suppressed. A typed error code or a dedicated `TRPCClientError` subtype would make the boundary explicit and rename-proof.

How can I resolve this? If you propose a fix, please make it concise.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

2 issues found across 3 files

Architecture diagram
sequenceDiagram
    participant Renderer as Renderer Process
    participant LocalHS as LocalHostServiceProvider
    participant Coordinator as HostServiceCoordinator (Main)
    participant DB as Host Service DB
    participant Child as Host Service Child

    Note over Renderer,Child: Starting the host service

    Renderer->>LocalHS: Use start mutation
    LocalHS->>LocalHS: Call electronTrpc.hostServiceCoordinator.start mutation
    LocalHS->>Coordinator: Invoke start()
    Coordinator->>Coordinator: Spawn child process (host-service)
    Coordinator->>Child: Execute

    alt Child process fails to start
        Coordinator-->>LocalHS: Rejection with error
        LocalHS->>LocalHS: NEW: onError handler
        alt Error is not "auth token" precondition
            LocalHS->>LocalHS: toast.error("Host service failed to start")
        end
        LocalHS-->>Renderer: No status update
    else Child starts successfully
        Coordinator-->>LocalHS: Success
        LocalHS-->>Renderer: Status = "running"
    end

    Note over Coordinator,Child: Startup phase - DB migration

    Child->>DB: Create database
    DB->>DB: Set busy_timeout = 5000
    DB->>DB: Run migrations
    alt Migration fails
        DB-->>Child: NEW: Throw error (no catch)
        Child->>Child: Crash (exit with error)
        Child-->>Coordinator: Unexpected exit
    else Migration succeeds
        DB-->>Child: Ready
        Child-->>Coordinator: Running normally
    end

    Note over Coordinator,Child: Runtime - unexpected child crash

    alt Child crashes while "running"
        Child-->>Coordinator: Exit event (code, signal)
        Coordinator->>Coordinator: Check status !== "stopped"
        Coordinator->>Coordinator: NEW: alertChildCrashed()
        Coordinator->>Coordinator: dialog.showMessageBox(error, buttons["Restart", "Dismiss"])
        Coordinator-->>Coordinator: User selects "Restart"
        Coordinator->>Coordinator: loadToken()
        Coordinator->>Coordinator: restart(organizationId, {authToken, cloudApiUrl})
        Coordinator->>Child: Spawn new child
        Child-->>Coordinator: New child running
    else Deliberate stop()
        Coordinator->>Coordinator: Set status = "stopped"
        Coordinator->>Child: Kill child
        Child-->>Coordinator: Exit event
        Coordinator->>Coordinator: Early return (no alert)
    end
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

@github-actions

github-actions Bot commented Jul 7, 2026 •

Copy link
Copy Markdown
Contributor

🚀 Preview Deployment

🔗 Preview Links

Service Status Link
Neon Database (Neon) ✅ View Branch
Vercel API (Vercel) ✅ Open Preview
Vercel Web (Vercel) ✅ Open Preview
Vercel Marketing (Vercel) ✅ Open Preview
Vercel Admin (Vercel) ✅ Open Preview
Vercel Docs (Vercel) ✅ Open Preview

Preview updates automatically with new commits

- drop Restart button (silent no-op when no token, flagged in review); recovery is the existing tray Restart. removes loadToken/env plumbing.
- emitStatus now reports the real prior status instead of hardcoded 'running' (child can die during the starting/health-poll window).
@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/desktop/src/main/lib/host-service-coordinator.ts (1)

523-535: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider identifying the affected organization in the crash dialog.

The dialog message says "unavailable ... for this organization" but never names the org, so with multiple concurrent host-service instances the user won't know which one crashed just from the alert.

💡 Optional improvement
 		log.error(`[host-service:${organizationId}] crashed (${cause})`);
 		dialog.showErrorBox(
 			"Host service crashed",
-			`The Superset host service stopped unexpectedly (${cause}). Workspaces and terminals for this organization are unavailable until it restarts — use the Superset tray menu > Host Service > Restart.`,
+			`The Superset host service for organization ${organizationId} stopped unexpectedly (${cause}). Workspaces and terminals for this organization are unavailable until it restarts — use the Superset tray menu > Host Service > Restart.`,
 		);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/main/lib/host-service-coordinator.ts` around lines 523 -
535, The crash dialog in alertChildCrashed only says “this organization” and
does not identify which org stopped, which is ambiguous when multiple
host-service instances are running. Update the dialog text built in
alertChildCrashed to include the affected organizationId alongside the existing
cause so the user can tell which organization’s workspaces and terminals are
unavailable. Keep the log line as-is, but ensure the dialog message itself names
the organization clearly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/desktop/src/main/lib/host-service-coordinator.ts`:
- Around line 523-535: The crash dialog in alertChildCrashed only says “this
organization” and does not identify which org stopped, which is ambiguous when
multiple host-service instances are running. Update the dialog text built in
alertChildCrashed to include the affected organizationId alongside the existing
cause so the user can tell which organization’s workspaces and terminals are
unavailable. Keep the log line as-is, but ensure the dialog message itself names
the organization clearly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a8ca0ea4-ce4b-490b-b57b-f666e95ad866

📥 Commits

Reviewing files that changed from the base of the PR and between 9d73fe9 and 0447aef.

📒 Files selected for processing (1)
  • apps/desktop/src/main/lib/host-service-coordinator.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/main/lib/host-service-coordinator.ts">

<violation number="1" location="apps/desktop/src/main/lib/host-service-coordinator.ts:533">
P2: On Windows/Linux, the crash dialog points users to a recovery path that does not exist because the Superset tray is only initialized on macOS. Consider using platform-neutral recovery text or gating the tray-specific instruction to macOS.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

log.error(`[host-service:${organizationId}] crashed (${cause})`);
dialog.showErrorBox(
"Host service crashed",
`The Superset host service stopped unexpectedly (${cause}). Workspaces and terminals for this organization are unavailable until it restarts — use the Superset tray menu > Host Service > Restart.`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: On Windows/Linux, the crash dialog points users to a recovery path that does not exist because the Superset tray is only initialized on macOS. Consider using platform-neutral recovery text or gating the tray-specific instruction to macOS.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/main/lib/host-service-coordinator.ts, line 533:

<comment>On Windows/Linux, the crash dialog points users to a recovery path that does not exist because the Superset tray is only initialized on macOS. Consider using platform-neutral recovery text or gating the tray-specific instruction to macOS.</comment>

<file context>
@@ -530,31 +528,10 @@ export class HostServiceCoordinator extends EventEmitter {
-			});
+		dialog.showErrorBox(
+			"Host service crashed",
+			`The Superset host service stopped unexpectedly (${cause}). Workspaces and terminals for this organization are unavailable until it restarts — use the Superset tray menu > Host Service > Restart.`,
+		);
 	}
</file context>
Suggested change
`The Superset host service stopped unexpectedly (${cause}). Workspaces and terminals for this organization are unavailable until it restarts — use the Superset tray menu > Host Service > Restart.`,
`The Superset host service stopped unexpectedly (${cause}). Workspaces and terminals for this organization are unavailable until it restarts — restart Superset to recover${process.platform === "darwin" ? ", or use the Superset tray menu > Host Service > Restart" : ""}.`,

@cursor

cursor Bot commented Jul 8, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

…ondition

Replaces the fragile error.message substring match with a TRPCError code so the auth-precondition filter is rename-proof (greptile P2).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
apps/desktop/src/main/lib/host-service-coordinator.ts (1)

516-533: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use showMessageBox if this dialog needs a Restart action

dialog.showErrorBox only renders a blocking OK dialog, so it can’t support the stated Restart flow. Switch to showMessageBox with explicit buttons and handle the selected action from a layer that has restart context.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/main/lib/host-service-coordinator.ts` around lines 516 -
533, The crash alert in alertChildCrashed currently uses dialog.showErrorBox,
which only supports a blocking OK dialog and cannot offer the Restart flow
described in the message. Replace it with dialog.showMessageBox in
host-service-coordinator.ts, and wire the response to a restart-capable handler
outside alertChildCrashed so the user can choose Restart explicitly; keep the
existing cause logging and message text, but move the action handling to the
layer that has restart context.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@apps/desktop/src/main/lib/host-service-coordinator.ts`:
- Around line 516-533: The crash alert in alertChildCrashed currently uses
dialog.showErrorBox, which only supports a blocking OK dialog and cannot offer
the Restart flow described in the message. Replace it with dialog.showMessageBox
in host-service-coordinator.ts, and wire the response to a restart-capable
handler outside alertChildCrashed so the user can choose Restart explicitly;
keep the existing cause logging and message text, but move the action handling
to the layer that has restart context.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 363940bb-8c64-4747-b073-2442c0c61709

📥 Commits

Reviewing files that changed from the base of the PR and between 0447aef and caf6fc5.

📒 Files selected for processing (3)
  • apps/desktop/src/main/lib/host-service-coordinator.ts
  • apps/desktop/src/renderer/routes/_authenticated/providers/LocalHostServiceProvider/LocalHostServiceProvider.tsx
  • packages/host-service/src/db/db.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/desktop/src/renderer/routes/_authenticated/providers/LocalHostServiceProvider/LocalHostServiceProvider.tsx
  • packages/host-service/src/db/db.ts

@cursor

cursor Bot commented Jul 8, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/desktop/src/lib/trpc/routers/host-service-coordinator/index.ts (1)

20-23: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: Extract the duplicated unauthorized-error throw into a helper.

The same TRPCError({ code: "UNAUTHORIZED", message: "No auth token available — user must be logged in" }) block is repeated in start, restart, and reset. A small helper would keep the message and code in one place and make future changes (e.g., different message or code) a single-line edit.

♻️ Suggested helper extraction
+function assertAuthToken(token: string | null): asserts token {
+	if (!token) {
+		throw new TRPCError({
+			code: "UNAUTHORIZED",
+			message: "No auth token available — user must be logged in",
+		});
+	}
+}

Then in each mutation:

 const { token } = await loadToken();
-if (!token) {
-	throw new TRPCError({
-		code: "UNAUTHORIZED",
-		message: "No auth token available — user must be logged in",
-	});
-}
+assertAuthToken(token);

Also applies to: 45-48, 60-63

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/lib/trpc/routers/host-service-coordinator/index.ts` around
lines 20 - 23, The same unauthorized TRPCError throw is duplicated across start,
restart, and reset in host-service-coordinator; extract it into a shared helper
so the code and message live in one place. Add a small function or factory near
the existing mutation handlers in index.ts, then replace each inline TRPCError({
code: "UNAUTHORIZED", message: "No auth token available — user must be logged
in" }) with that helper to keep future edits centralized.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/desktop/src/lib/trpc/routers/host-service-coordinator/index.ts`:
- Around line 20-23: The same unauthorized TRPCError throw is duplicated across
start, restart, and reset in host-service-coordinator; extract it into a shared
helper so the code and message live in one place. Add a small function or
factory near the existing mutation handlers in index.ts, then replace each
inline TRPCError({ code: "UNAUTHORIZED", message: "No auth token available —
user must be logged in" }) with that helper to keep future edits centralized.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a01bfb04-ae86-4275-b7b0-4efc64496e99

📥 Commits

Reviewing files that changed from the base of the PR and between caf6fc5 and c0b68b4.

📒 Files selected for processing (2)
  • apps/desktop/src/lib/trpc/routers/host-service-coordinator/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/providers/LocalHostServiceProvider/LocalHostServiceProvider.tsx

@Kitenite
Kitenite merged commit 55867ab into main Jul 8, 2026
10 of 11 checks passed
@Kitenite
Kitenite deleted the host-service-direct-run branch July 8, 2026 18:59
saddlepaddle added a commit that referenced this pull request Jul 9, 2026
… test

#5493 added dialog.showErrorBox to the coordinator but the test file's
electron mock only exported app, so the suite fails at import. Broke on
main between the 17:17Z and 18:59Z CI runs.
saddlepaddle added a commit that referenced this pull request Jul 9, 2026
* feat(mobile): EAS TestFlight build and submit configuration

- eas.json: preview/production profiles pull EXPO_PUBLIC_* from EAS
  environment variables; submit profile pinned to the App Store Connect
  app (ascAppId) and Apple team
- app.config.ts: expo-image-picker plugin with photo library usage
  string (camera/microphone disabled), expo-document-picker plugin
- store.config.json: EAS Metadata store listing config
- assets/icon.png: flatten unused alpha channel (App Store rejects
  1024px icons with alpha)
- .env.example: document mobile EXPO_PUBLIC_* variables

* feat(mobile): populate EXPO_PUBLIC_* env vars in local dev setup

setup.local.sh and .env.local.example now provide the mobile app's
required env vars. Electric points at the plain-HTTP electric-proxy
wrangler server since React Native fetch rejects Caddy's self-signed
certificate. Also switch App Review contact to support@superset.sh.

* fix(desktop): add dialog to electron mock in host-service-coordinator test

#5493 added dialog.showErrorBox to the coordinator but the test file's
electron mock only exported app, so the suite fails at import. Broke on
main between the 17:17Z and 18:59Z CI runs.

This branch was previously deployed

1 inactive deployment
preview — c0b68b43 Deployed Jul 8, 2026 by Kitenite via Deploy Admin #6259
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