zed-industries/zed · error
failed to bind callback port
Error message
failed to bind callback port
What it means
For native app sign-in, Zed starts a tiny HTTP server on 127.0.0.1:0 (ephemeral port) to receive the OAuth redirect. This error means the loopback bind itself failed, so no callback can ever arrive.
Source
Thrown at crates/client/src/client.rs:1471
rpc::auth::keypair().context("failed to generate keypair for auth")?;
let public_key = String::try_from(public_key)
.context("failed to serialize public key for auth")?;
if let Some((login, token)) =
IMPERSONATE_LOGIN.as_ref().zip(ADMIN_API_TOKEN.as_ref())
{
if !*USE_WEB_LOGIN {
eprintln!("authenticate as admin {login}, {token}");
return this
.authenticate_as_admin(http, login.clone(), token.clone())
.await;
}
}
// Start an HTTP server to receive the redirect from Zed's sign-in page.
let server = tiny_http::Server::http("127.0.0.1:0")
.map_err(|e| anyhow!(e).context("failed to bind callback port"))?;
let port = server
.server_addr()
.to_ip()
.context("server not bound to a TCP address")?
.port();
#[derive(Serialize)]
struct NativeAppSignInQueryParams {
native_app_port: u16,
native_app_public_key: String,
system_id: Option<Arc<str>>,
}
// Open the Zed sign-in page in the user's browser, with query parameters that indicate
// that the user is signing in from a Zed app running on the same device.
let url = http.build_url(&format!(
"/native_app_signin?{}",
serde_urlencoded::to_string(&NativeAppSignInQueryParams {View on GitHub (pinned to bc538def45)
Solutions
- Run Zed outside sandboxed/containerized environments that block loopback listeners
- Check for port exhaustion: close runaway local processes and retry
- Temporarily test with the app firewall/security agent disabled to confirm the blocker
Defensive patterns
Strategy: retry
Validate before calling
// probe loopback bind capability before starting sign-in
fn loopback_available() -> bool {
std::net::TcpListener::bind("127.0.0.1:0").is_ok()
}
if !loopback_available() {
anyhow::bail!("cannot bind loopback; native sign-in unavailable in this environment");
} Try / catch
let server = match tiny_http::Server::http("127.0.0.1:0") {
Ok(server) => server,
Err(err) if err.kind() == std::io::ErrorKind::AddrInUse || err.kind() == std::io::ErrorKind::PermissionDenied => {
// transient on busy systems; brief backoff then one retry
std::thread::sleep(Duration::from_millis(500));
tiny_http::Server::http("127.0.0.1:0").map_err(|e| anyhow!(e).context("failed to bind callback port"))?
}
Err(err) => return Err(anyhow!(err).context("failed to bind callback port")),
}; Prevention
- Avoid running sign-in inside sandboxed containers without loopback
- Monitor local socket usage on shared CI machines
- Fall back to non-native sign-in flows where listeners are blocked
When it happens
Trigger: tiny_http::Server::http("127.0.0.1:0") returns an error: the OS refuses new sockets — exhausted port range, sandbox denying network listeners, or restrictive container/MAC policies.
Common situations: Running Zed inside a sandboxed environment or container without loopback networking; systems with thousands of TIME_WAIT sockets; macOS application-firewall or endpoint-security agents blocking listeners.
Related errors
- authentication canceled
- didn't receive login redirect
- Failed to parse UNIT_DATA as JSON: ${e.message}
- HTTP error! status: ${response.status}
- Slack webhook returned {response.status_code}: {response.tex
AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16).
Data as JSON: /api/errors/c0a739161dee94e6.
Report an issue: GitHub.