Skip to content

fix(desktop): recover from local service port conflicts - #53888

Closed
OpeOginni wants to merge 3 commits into
anomalyco:devfrom
OpeOginni:desktop-port-recovery
Closed

OpeOginni wants to merge 3 commits into
anomalyco:devfrom
OpeOginni:desktop-port-recovery

Conversation

@OpeOginni

@OpeOginni OpeOginni commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Issue for this PR

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

  • Show a clear port-conflict message while keeping the full, copyable error output visible.
  • Let desktop users set another port and restart, using the bundled CLI's existing service configuration command.
  • Carry the confirmed bind failure through a private startup pipe and desktop IPC. Error text alone never enables port recovery.
  • Wait for surviving startup attempts before reporting a confirmed conflict, without recruiting replacements after a failure.
  • Preserve the real message instead of Solid's "Unknown error" wrapper, including ordinary IPC errors and their diagnostics.
  • Keep the usual error page for other failures. No dev-launcher changes are included.

How did you verify your code works?

  • bun run check passes.
  • Focused app, desktop IPC/startup, and Promise/Effect service tests pass.
  • Real CLI tests pass with an occupied port, a port released during startup, and an incumbent appearing during startup.
  • The Node-to-compiled-CLI port-conflict smoke test passes on macOS and is included in the existing Linux/Windows CI smoke checks. Windows verification is pending CI.
  • The conflict screen was reproduced locally. Save-and-relaunch manual verification is still pending.

Screenshots / recordings

Trimmed.PR.Screen.recording.mov

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

@opencode-agent opencode-agent 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.

I checked the CLI/client side outside the app. With the configured port held by an unrelated listener, Service.ensure on the base fails after ~21s with a generic "Server process exited with code 1". With this PR it fails after ~16s with a typed PortConflictError carrying the port. The new and nearby client, CLI, desktop and app tests pass, and all four packages type-check. I couldn't run the desktop app, so the conflict screen and save-and-relaunch are untested here, as the description also says. A recording of that flow would help.

The design holds up: recovery is only offered for a conflict reported through the private pipe, never from stderr text; the port is validated both in the IPC schema and in the form; and service set port only writes config. The new tests are small and to the point. Two concerns (inline): failing early can leave the other startup attempt running in the background, where it may still bind the port; and the file-descriptor-3 pipe needs a check on Windows.

),
)
yield* Effect.try(() => {
if (startupPipe) writeSync(3, JSON.stringify({ type: "port-conflict", hostname, port }))

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.

This assumes the bundled Bun executable can write to an extra pipe inherited from Electron's spawn as file descriptor 3. That works on Linux, but please confirm it on Windows. If the write fails there, it is silently ignored and users get the generic error page with no recovery. That's no worse than today, but it means the fix quietly doesn't apply on Windows.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added an end-to-end smoke check using the actual Node service client to spawn the compiled CLI and assert receipt of PortConflictError. It passes on macOS and is included in the existing Linux/Windows CI smoke checks. Windows verification is still pending; I’m not claiming platform confirmation yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

1 participant