Skip to content

Commit bc1cbff

Browse files
committed
fix(desktop): explain macOS Local Network blocks for private self-hosted servers
1 parent 83914e7 commit bc1cbff

4 files changed

Lines changed: 32 additions & 2 deletions

File tree

‎apps/desktop/electron-builder.yml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ mac:
7272
NSScreenCaptureUsageDescription: Mothership captures approved app windows to understand and verify computer-use actions.
7373
NSMicrophoneUsageDescription: Sim uses your microphone for voice input in Chat and for meetings you join in the built-in browser.
7474
NSCameraUsageDescription: Sim uses your camera for meetings you join in the built-in browser, such as Google Meet.
75+
# macOS 15 blocks connections to private addresses (self-hosted servers on a
76+
# LAN or VPN) until the user allows Sim; this string explains that prompt.
77+
NSLocalNetworkUsageDescription: Sim connects to your self-hosted Sim server and to local addresses you open in the built-in browser.
7578
entitlements: build/entitlements.mac.plist
7679
entitlementsInherit: build/entitlements.mac.plist
7780
notarize: true

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ describe('classifyLoadError', () => {
77
expect(classifyLoadError(-2)).toBe('unreachable')
88
expect(classifyLoadError(-1)).toBe('unreachable')
99
})
10+
11+
it('reports ERR_ADDRESS_UNREACHABLE as a local-network block only on macOS', () => {
12+
expect(classifyLoadError(-109, 'darwin')).toBe('local_network')
13+
expect(classifyLoadError(-109, 'linux')).toBe('unreachable')
14+
expect(classifyLoadError(-109, 'win32')).toBe('unreachable')
15+
})
1016
})
1117

1218
vi.mock('electron', () => import('@/test/electron-mock'))

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,23 @@ const logger = createLogger('DesktopLoadHealth')
77
const AUTO_RETRY_INTERVAL_MS = 5000
88
const LOAD_WATCHDOG_MS = 30_000
99

10-
export type LoadErrorKind = 'offline' | 'dns' | 'tls' | 'timeout' | 'unreachable' | 'ignored'
10+
export type LoadErrorKind =
11+
| 'offline'
12+
| 'dns'
13+
| 'tls'
14+
| 'timeout'
15+
| 'local_network'
16+
| 'unreachable'
17+
| 'ignored'
1118

1219
/**
1320
* Maps Chromium net error codes to recovery copy. -3 (ERR_ABORTED) is emitted
1421
* constantly by OAuth redirect chains and in-app aborts and must be ignored.
1522
*/
16-
export function classifyLoadError(errorCode: number): LoadErrorKind {
23+
export function classifyLoadError(
24+
errorCode: number,
25+
platform: NodeJS.Platform = process.platform
26+
): LoadErrorKind {
1727
// Only ERR_ABORTED (-3) and success (0) are ignored. ERR_FAILED (-2) and
1828
// ERR_IO_PENDING (-1) are real failures that must surface the offline page.
1929
if (errorCode === 0 || errorCode === -3) {
@@ -31,6 +41,12 @@ export function classifyLoadError(errorCode: number): LoadErrorKind {
3141
if (errorCode <= -200 && errorCode >= -213) {
3242
return 'tls'
3343
}
44+
// macOS Local Network privacy fails the socket with EHOSTUNREACH, which
45+
// Chromium reports as ERR_ADDRESS_UNREACHABLE (-109), so a self-hosted server
46+
// on a private address looks like a routing failure until Sim is allowed.
47+
if (errorCode === -109 && platform === 'darwin') {
48+
return 'local_network'
49+
}
3450
return 'unreachable'
3551
}
3652

‎apps/desktop/src/renderer/offline/index.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ const ERROR_COPY = {
3030
title: 'The server isn’t responding',
3131
message: 'The connection timed out. The server may be down or your network may be blocking it.',
3232
},
33+
local_network: {
34+
title: 'Can’t reach the server',
35+
message:
36+
'If your Sim server is on a local or private network, macOS may be blocking Sim. Turn on Sim in System Settings > Privacy & Security > Local Network, then try again.',
37+
},
3338
unreachable: {
3439
title: 'Can’t connect to Sim',
3540
message: 'Sim couldn’t reach the server. Check your internet connection, then try again.',

0 commit comments

Comments
 (0)