Skip to content

fix(desktop): refuse same-home port fallback - #9003

Open
maxibotstef wants to merge 1 commit into
pingdotgg:mainfrom
maxibotstef:fix/desktop-no-same-home-port-fallback
Open

maxibotstef wants to merge 1 commit into
pingdotgg:mainfrom
maxibotstef:fix/desktop-no-same-home-port-fallback

Conversation

@maxibotstef

@maxibotstef maxibotstef commented Sep 1, 2026 •

Copy link
Copy Markdown

What Changed

Packaged Desktop startup now uses the default backend port (3773) or fails before spawning the embedded server. It no longer scans to 3774+ while retaining the same T3 home.

An explicitly configured T3CODE_PORT still behaves as before.

Why

If an older/background T3 backend already owns 3773, the sequential scan currently launches another backend on 3774 against the same state.sqlite, settings, and provider state. The second backend appears healthy but creates split-brain writers; with Codex single-writer thread persistence this can surface as thread <id> already has an active writer.

Failing before primaryBackend.start closes that Desktop-specific path without requiring process killing, database repair, or a speculative attach/auth lifecycle. The error explains that automatic fallback is intentionally refused and names the safe choices.

This is the small Desktop boundary from #6097. Generic server-level ownership remains separate in #8442/#8960.

Fixes #6097.

UI Changes

Only the existing fatal-startup error box changes: when default port 3773 is occupied, it now explains that T3 will not start a second same-home backend on a fallback port. No ordinary-startup UI changes.

Verification

  • pnpm exec vp test run apps/desktop/src/app/DesktopAppErrors.test.ts — 5 passed
  • pnpm exec vp run --filter @t3tools/desktop typecheck
  • targeted lint and format checks
  • exact committed two-file source review — GLM GO, no findings

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes (error-only startup path; not captured)
  • I included a video for animation/interaction changes (n/a)

Scope check: no attach-to-existing flow, server lock, provider lifecycle, or live-state change is included.

Model: GPT-5.6 Sol
Harness: T3 Code / Codex


Note

Medium Risk
Changes desktop startup behavior when the default port is busy—users see a fatal error instead of a silent fallback that could cause split-brain SQLite writers—but scope is limited to port resolution with explicit T3CODE_PORT unchanged.

Overview
Packaged desktop startup no longer scans from 3773 upward for a free backend port. When no T3CODE_PORT is set, it only uses the default port or fails fast if that port cannot bind on the usual probe hosts.

DesktopBackendPortUnavailableError is replaced by DesktopBackendPortInUseError, with a clearer multi-line message that explains T3 Code will not start a second backend on a fallback port against the same data directory. Bootstrap logging drops the “selected via sequential scan” path and only distinguishes configured vs default port.

resolveDesktopBackendPort is exported for testing. DesktopAppErrors.test.ts adds Effect tests with a stub NetService to cover default-port success, occupied-port refusal (probes only 3773, no scan), and explicit port passthrough.

Reviewed by Cursor Bugbot for commit 6a426bd. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Refuse same-home port fallback in resolveDesktopBackendPort

  • When no explicit port is configured, resolveDesktopBackendPort now probes only DEFAULT_DESKTOP_BACKEND_PORT across DESKTOP_BACKEND_PORT_PROBE_HOSTS; if any host cannot bind, it throws DesktopBackendPortInUseError with { port, hosts } instead of scanning for an alternative port.
  • Replaces DesktopBackendPortUnavailableError (which carried { startPort, maxPort, hosts }) with DesktopBackendPortInUseError (carrying { port, hosts }), whose message advises stopping the running server or changing T3CODE_HOME.
  • Removes the MAX_TCP_PORT constant and the selectedByScan return field; updates desktop.bootstrap logging accordingly.
  • Risk: callers expecting { port, selectedByScan } or catching DesktopBackendPortUnavailableError will break — in-tree usages in DesktopApp.ts and DesktopAppErrors.test.ts are updated, but out-of-tree consumers are not.

Macroscope summarized 6a426bd.

@github-actions github-actions Bot added size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Sep 1, 2026
@macroscopeapp

macroscopeapp Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This changes packaged desktop startup behavior for the default port, replacing automatic fallback with a fatal startup error before the backend is spawned. Because the product default behavior changes and startup is gated by the port probe, the change merits human review.

You can add or adjust custom eligibility rules. Learn more.

This branch has not been deployed

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

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Desktop starts a second backend against the background service database

1 participant