From 7dc7df9594037360d3445d8fb7d4b6c9613a5041 Mon Sep 17 00:00:00 2001 From: MasterYoav Date: Fri, 18 Sep 2026 10:26:16 +0300 Subject: [PATCH] OrbStack says Bad Gateway where Docker Desktop says no such host. Measured against OrbStack 29.4: an unreachable registry comes back as the proxy's answer, which fell through to "The engine couldn't start" on a first run with the network down. Co-Authored-By: Claude Opus 5 (1M context) --- .../mac/Sources/XBotRuntime/ContainerDriver.swift | 3 +++ .../mac/Tests/XBotRuntimeTests/RuntimeTests.swift | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/apps/mac/Sources/XBotRuntime/ContainerDriver.swift b/apps/mac/Sources/XBotRuntime/ContainerDriver.swift index 70fb29e..f68d148 100644 --- a/apps/mac/Sources/XBotRuntime/ContainerDriver.swift +++ b/apps/mac/Sources/XBotRuntime/ContainerDriver.swift @@ -238,6 +238,9 @@ public enum RuntimeError: Error, Sendable, Equatable { "dial tcp", "no such host", "i/o timeout", "tls handshake timeout", "connection reset", "connection refused", "unexpected eof", "network is unreachable", "context deadline exceeded", "net/http", + // OrbStack's daemon goes through a proxy, so an unreachable registry reaches us as + // the proxy's answer rather than Docker Desktop's `no such host`. + "bad gateway", "gateway timeout", ] if network.contains(where: text.contains) { return .downloadInterrupted } } diff --git a/apps/mac/Tests/XBotRuntimeTests/RuntimeTests.swift b/apps/mac/Tests/XBotRuntimeTests/RuntimeTests.swift index 643b6fe..8a5a9a9 100644 --- a/apps/mac/Tests/XBotRuntimeTests/RuntimeTests.swift +++ b/apps/mac/Tests/XBotRuntimeTests/RuntimeTests.swift @@ -994,6 +994,21 @@ struct CommandFailureKindTests { } } + /** + OrbStack words an unreachable registry differently from Docker Desktop. + + Its daemon reaches out through a proxy, so a lookup that fails comes back as the proxy's + "Bad Gateway" rather than Docker Desktop's `no such host`. Measured, not guessed: this is the + exact line OrbStack 29.4 printed for a registry that does not resolve. Unmatched, it fell through + to "The engine couldn't start" — on a first run with the network down, and on the runtime a + developer-leaning Mac is most likely to already have. + */ + @Test func aDownloadThatLostTheNetworkThroughOrbStacksProxy() { + let message = #"Error response from daemon: Get "https://ghcr.io/v2/": Bad Gateway"# + #expect(kind(pull, message) == .downloadInterrupted) + #expect(kind(pull, "Error response from daemon: Get \"https://ghcr.io/v2/\": Gateway Timeout") == .downloadInterrupted) + } + @Test func aDiskThatFilled() { let message = "failed to register layer: write /var/lib/docker/overlay2/x/diff/usr/lib/libx.so: no space left on device" #expect(kind(pull, message) == .diskFull)