Skip to content

Commit fb41a22

Browse files
cyberpapiiiclaude
andcommitted
fix: propagate server errors instead of leaking continuation
The withCheckedContinuation that never resumed caused two problems: 1. SWIFT TASK CONTINUATION MISUSE runtime warnings 2. If Hummingbird crashed in the background Task, the error was silently swallowed — the process stayed alive but stopped accepting connections, causing silent disconnects from MCP Router with no auto-recovery. Now main.swift awaits transport.waitForTermination() which propagates errors from the server Task. If the server dies, the process exits and launchd restarts it, allowing MCP Router to reconnect. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3a9a06c commit fb41a22

File tree

2 files changed

+11
-3
lines changed

2 files changed

+11
-3
lines changed

swift/Sources/iMessageMax/Server/HTTPTransport.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,16 @@ public actor HTTPTransport: Transport {
128128
}
129129
}
130130

131+
/// Blocks until the server terminates, propagating any errors.
132+
///
133+
/// Call this from main.swift after `connect()`. If the Hummingbird server
134+
/// crashes or encounters an error, it propagates here — causing the process
135+
/// to exit so launchd can restart it.
136+
public func waitForTermination() async throws {
137+
guard let task = serverTask else { return }
138+
try await task.value
139+
}
140+
131141
/// Handles POST requests with JSON-RPC messages
132142
private func handlePost(
133143
request: Request,

swift/Sources/iMessageMax/main.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,7 @@ struct iMessageMax: AsyncParsableCommand {
5656
)
5757

5858
try await transport.connect()
59-
await withCheckedContinuation { (_: CheckedContinuation<Void, Never>) in
60-
// Server runs indefinitely until process is terminated
61-
}
59+
try await transport.waitForTermination()
6260
} else {
6361
// Stdio mode: Single Server instance managed by MCPServerWrapper
6462
let server = MCPServerWrapper()

0 commit comments

Comments
 (0)