Bug
auths pair (LAN mode) prints the QR code and debug curl line, but the HTTP server never accepts connections. lsof -i :<port> shows nothing listening. curl localhost:<port>/health returns connection refused.
Root cause
In crates/auths-cli/src/commands/device/pair/lan_server.rs, line 107:
pub async fn wait_for_response(
self,
timeout: Duration,
) -> Result<SubmitResponseRequest, auths_sdk::error::PairingError> {
self.cancel.cancel(); // ← BUG: cancels the server IMMEDIATELY
self.handle
.wait_for_response(timeout)
.await
...
}
The CancellationToken::cancel() is called as the first action in wait_for_response. This triggers the cancel_clone.cancelled() branch in the server's tokio::select! (line 65), shutting down the axum server before any connections can be accepted.
The cancellation token is meant for cleanup after the pairing completes or times out — not as the first action when waiting begins.
Flow
LanPairingServer::start() binds a TcpListener, spawns the axum server in a tokio::spawn with a CancellationToken
- CLI prints QR code, short code, and debug curl line
server.wait_for_response(expiry_duration).await is called (lan.rs:182)
self.cancel.cancel() fires immediately (lan_server.rs:107)
- The
tokio::select! in the spawned task sees cancelled() resolve → exits
- Server stops listening. No connections ever accepted.
Fix
Move self.cancel.cancel() to after the response is received (or after timeout), not before:
pub async fn wait_for_response(
self,
timeout: Duration,
) -> Result<SubmitResponseRequest, auths_sdk::error::PairingError> {
let result = self.handle
.wait_for_response(timeout)
.await
.map_err(|e| match e {
auths_pairing_daemon::DaemonError::Pairing(pe) => pe,
other => auths_sdk::error::PairingError::LocalServerError(other.to_string()),
});
// Shut down the server AFTER we have the response (or timed out)
self.cancel.cancel();
result
}
Reproduction
auths pair # starts LAN pairing
# In another terminal:
curl http://127.0.0.1:<port>/health # connection refused
lsof -i :<port> # empty
Affected version
Current main and dev-pairingHardening branch.
Bug
auths pair(LAN mode) prints the QR code and debug curl line, but the HTTP server never accepts connections.lsof -i :<port>shows nothing listening.curl localhost:<port>/healthreturns connection refused.Root cause
In
crates/auths-cli/src/commands/device/pair/lan_server.rs, line 107:The
CancellationToken::cancel()is called as the first action inwait_for_response. This triggers thecancel_clone.cancelled()branch in the server'stokio::select!(line 65), shutting down the axum server before any connections can be accepted.The cancellation token is meant for cleanup after the pairing completes or times out — not as the first action when waiting begins.
Flow
LanPairingServer::start()binds aTcpListener, spawns the axum server in atokio::spawnwith aCancellationTokenserver.wait_for_response(expiry_duration).awaitis called (lan.rs:182)self.cancel.cancel()fires immediately (lan_server.rs:107)tokio::select!in the spawned task seescancelled()resolve → exitsFix
Move
self.cancel.cancel()to after the response is received (or after timeout), not before:Reproduction
Affected version
Current
mainanddev-pairingHardeningbranch.