Skip to content

Commit c808a88

Browse files
authored
fix(desktop): skip the Local Network hint when Sim Cloud is unreachable (#9791)
On macOS 15+ every ERR_ADDRESS_UNREACHABLE load failure was explained as a Local Network privacy block, including failures to reach Sim Cloud, which is public and never gated by that permission. classifyLoadError now takes the failed URL and keeps the hint for self-hosted servers only, including ones reached through a DNS name that resolves to a private address.
1 parent 776c33a commit c808a88

2 files changed

Lines changed: 15 additions & 6 deletions

File tree

‎apps/desktop/src/main/load-health.test.ts‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,20 @@ import { attachLoadHealth, classifyLoadError } from '@/main/load-health'
33
import { BrowserWindow as MockBrowserWindow } from '@/test/electron-mock'
44

55
describe('classifyLoadError', () => {
6+
const SELF_HOSTED_URL = 'http://sim.corp.internal:3000/workspace'
7+
68
it('does NOT ignore ERR_FAILED (-2) or ERR_IO_PENDING (-1)', () => {
7-
expect(classifyLoadError(-2)).toBe('unreachable')
8-
expect(classifyLoadError(-1)).toBe('unreachable')
9+
expect(classifyLoadError(-2, SELF_HOSTED_URL)).toBe('unreachable')
10+
expect(classifyLoadError(-1, SELF_HOSTED_URL)).toBe('unreachable')
911
})
1012

1113
it('reports ERR_ADDRESS_UNREACHABLE as a local-network block only under Local Network privacy', () => {
12-
expect(classifyLoadError(-109, true)).toBe('local_network')
13-
expect(classifyLoadError(-109, false)).toBe('unreachable')
14+
expect(classifyLoadError(-109, SELF_HOSTED_URL, true)).toBe('local_network')
15+
expect(classifyLoadError(-109, SELF_HOSTED_URL, false)).toBe('unreachable')
16+
})
17+
18+
it('never blames Local Network privacy for Sim Cloud, which is public', () => {
19+
expect(classifyLoadError(-109, 'https://www.sim.ai/workspace', true)).toBe('unreachable')
1420
})
1521
})
1622

‎apps/desktop/src/main/load-health.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { release } from 'node:os'
22
import { createLogger } from '@sim/logger'
33
import type { BrowserWindow } from 'electron'
4+
import { isSimCloudOrigin } from '@/main/config'
45
import { type EventRecorder, scrubUrl } from '@/main/observability'
56

67
const logger = createLogger('DesktopLoadHealth')
@@ -32,6 +33,7 @@ export type LoadErrorKind =
3233
*/
3334
export function classifyLoadError(
3435
errorCode: number,
36+
url: string,
3537
localNetworkPrivacy: boolean = hasLocalNetworkPrivacy()
3638
): LoadErrorKind {
3739
// Only ERR_ABORTED (-3) and success (0) are ignored. ERR_FAILED (-2) and
@@ -54,7 +56,8 @@ export function classifyLoadError(
5456
// macOS Local Network privacy fails the socket with EHOSTUNREACH, which
5557
// Chromium reports as ERR_ADDRESS_UNREACHABLE (-109), so a self-hosted server
5658
// on a private address looks like a routing failure until Sim is allowed.
57-
if (errorCode === -109 && localNetworkPrivacy) {
59+
// Sim Cloud is public, so that permission can never be what blocked it.
60+
if (errorCode === -109 && localNetworkPrivacy && !isSimCloudOrigin(url)) {
5861
return 'local_network'
5962
}
6063
return 'unreachable'
@@ -151,7 +154,7 @@ export function attachLoadHealth(win: BrowserWindow, deps: LoadHealthDeps): Load
151154
return
152155
}
153156
clearTimeout(watchdogTimer)
154-
const kind = classifyLoadError(errorCode)
157+
const kind = classifyLoadError(errorCode, validatedURL)
155158
if (kind === 'ignored') {
156159
return
157160
}

0 commit comments

Comments
 (0)