Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/mac/Sources/XBotRuntime/ContainerDriver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
}
Expand Down
15 changes: 15 additions & 0 deletions apps/mac/Tests/XBotRuntimeTests/RuntimeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading