Skip to content

fix(cursor-proxy): fix double-wrapped Result hiding setup failures#3428

Merged
la14-1 merged 2 commits into
graphite-base/3428from
cursor-proxy/fix-error-reporting
May 22, 2026
Merged

fix(cursor-proxy): fix double-wrapped Result hiding setup failures#3428
la14-1 merged 2 commits into
graphite-base/3428from
cursor-proxy/fix-error-reporting

Conversation

@aulorbe
Copy link
Copy Markdown
Collaborator

@aulorbe aulorbe commented May 21, 2026

Summary

Fixes misleading proxy setup output where every step reports success even when it fails. For example, a completely broken setup would print:

Cursor proxy failed to start    ← shell script's own error (stderr, red)
Cursor proxy started            ← TypeScript's success log (green)

…and similarly "Caddy available" after Caddy install fails, "Hosts spoofing configured" after /etc/hosts: Permission denied, etc.

Root cause

setupCursorProxy and startCursorProxy used asyncTryCatchIf(isOperationalError, () => wrapSshCall(...)), which double-wraps the Result. wrapSshCall already catches errors and returns Err() (it doesn't throw), so asyncTryCatchIf always sees a successful return and wraps it in Ok(Err(...)). Checking result.ok on the outer wrapper is always true — the error branch is unreachable.

Fix

  • Call wrapSshCall directly and check its returned Result (remove asyncTryCatchIf wrapper).
  • Add early-return with accurate warning messages on deploy and hosts failures so errors don't cascade silently.
  • Add macOS DNS cache flush (dscacheutil -flushcache + killall -HUP mDNSResponder) after /etc/hosts modification to prevent stale DNS from bypassing the proxy.

Stacked on cursor-proxy/model-selectioncursor-proxy/macos-compat.

Test plan

  • bun test src/__tests__/cursor-proxy.test.ts — all 13 tests pass
  • bunx @biomejs/biome check src/shared/cursor-proxy.ts — zero errors
  • Run SPAWN_CLI_DIR=. bun run dev locally, verify failure messages are accurate when a step fails
  • Run successful local spawn, verify success messages still appear correctly

The error handling in setupCursorProxy and startCursorProxy used
asyncTryCatchIf(isOperationalError, () => wrapSshCall(...)) which
double-wrapped the Result: wrapSshCall returns Err() on failure
(doesn't throw), so asyncTryCatchIf always saw a successful return
and wrapped it in Ok(Err(...)). This meant result.ok was always
true, causing misleading output like "Cursor proxy started" even
when every step failed.

Fix: call wrapSshCall directly and check its returned Result.
Also adds macOS DNS cache flush after /etc/hosts modification and
early-return on deploy/hosts failure with accurate warning messages.
@graphite-app graphite-app Bot changed the base branch from cursor-proxy/model-selection to graphite-base/3428 May 21, 2026 23:26
…s used (#3429)

* fix(cli): inject SPAWN_CLI_DIR in dev script so local source is always used

Without SPAWN_CLI_DIR, `bun run dev` downloads the spawn script from
the published CDN release, ignoring any local source changes. This is
especially confusing when developing on a branch with fixes that
haven't been published yet.

Set SPAWN_CLI_DIR to the repo root (via git rev-parse) in the dev
script so the local checkout is always used during development.

* docs(cursor): add model picker and provider notes for local spawn (#3431)

Add a section to sh/local/README.md noting that the "Custom model"
setup option must be selected to get the OpenRouter model picker when
spawning Cursor locally, and that only Cursor IDE-supported providers
work (linking to Cursor's supported providers docs).
@la14-1 la14-1 merged commit 67215c0 into graphite-base/3428 May 22, 2026
1 check was pending
@la14-1 la14-1 deleted the cursor-proxy/fix-error-reporting branch May 22, 2026 00:38
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.

3 participants