jlcodes99/cockpit-tools · error
本地回调服务异常: {}
Error message
本地回调服务异常: {} What it means
Logged during restore_pending_oauth_listener when re-creating the Kiro OAuth local HTTP callback server (for a pending login identified by login_id/state) fails. The error is stored as the callback result for that login, so any client waiting on the login future receives "本地回调服务异常: {reason}" instead of tokens.
Source
Thrown at crates/cockpit-core/src/modules/kiro_oauth.rs:134
if state.callback_result.is_some() {
return;
}
match TcpListener::bind(("127.0.0.1", state.callback_port)) {
Ok(listener) => {
drop(listener);
let expected_login_id = state.login_id.clone();
let expected_state = state.state_token.clone();
let callback_port = state.callback_port;
tokio::spawn(async move {
if let Err(err) = start_callback_server(
callback_port,
expected_login_id.clone(),
expected_state.clone(),
)
.await
{
logger::log_error(&format!(
"[Kiro OAuth] 回调服务恢复失败: login_id={}, error={}",
expected_login_id, err
));
set_callback_result_for_login(
&expected_login_id,
&expected_state,
Err(format!("本地回调服务异常: {}", err)),
);
}
});
logger::log_info(&format!(
"[Kiro OAuth] 已恢复本地回调服务: login_id={}, port={}",
state.login_id, state.callback_port
));
}
Err(err) if err.kind() == ErrorKind::AddrInUse => {
logger::log_info(&format!(
"[Kiro OAuth] 本地回调端口已占用,视为监听中: login_id={}, port={}",View on GitHub (pinned to 1ed8b77992)
Solutions
- Free the configured callback_port (find and kill the process listening on it, e.g. `lsof -i :PORT`).
- Cancel the stale pending login and start a fresh Kiro OAuth login instead of restoring the old one.
- Configure a different, unprivileged callback port (>1024) in settings.
- Check firewall/antivirus policies that may prevent binding a local listener.
- Retry after ensuring no duplicate app instance is running.
Example fix
// before: blindly reusing the fixed callback port
let port = 17850;
// after: detect a busy port before starting login
fn port_free(p: u16) -> bool { std::net::TcpListener::bind(("127.0.0.1", p)).is_ok() }
let port = if port_free(17850) { 17850 } else { pick_free_port() }; Defensive patterns
Strategy: validation
Validate before calling
// Check the callback port is bindable before restoring a pending login
fn callback_port_free(port: u16) -> bool {
std::net::TcpListener::bind(("127.0.0.1", port)).is_ok()
}
if !callback_port_free(callback_port) {
return Err(format!("callback port {} occupied; free it or pick another", callback_port));
} Type guard
fn is_callback_server_error(err: &str) -> bool {
err.starts_with("本地回调服务异常: ")
} Try / catch
match restore_pending_oauth_listener(&login_id, &state).await {
Err(err) if is_callback_server_error(&err) => {
cancel_pending_login(&login_id);
ui.prompt("本地回调端口被占用,请释放端口后重新登录");
}
other => handle(other),
} Prevention
- Use an unprivileged, rarely-conflicting callback port and make it configurable.
- Cancel pending OAuth state cleanly instead of letting stale listeners linger.
- Avoid running multiple app instances during login.
- Check `lsof -i :PORT` / `netstat -ano | findstr PORT` when login hangs.
- Allow loopback socket binding in firewall/AV policies.
When it happens
Trigger: Calling start_login or restore_pending_oauth_listener where a previous pending OAuth flow exists and start_callback_server_for_state cannot bind the callback_port (address already in use, permission denied) or fails while initializing the listener.
Common situations: Port already occupied by a previous crashed/zombie listener or another app; firewall blocking local binding; app restarted mid-login leaving a stale pending state that cannot be restored; privileged/low port configured; SELinux/security software blocking socket bind.
Related errors
- [Windsurf OAuth] 回调服务恢复失败: login_id={}, error={}
- [Windsurf OAuth] 回调服务异常: login_id={}, error={}
- OAuth 回调服务器错误: {}
- OAuth 回调服务器错误: {}
- OAuth 流程失败: {}
AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05).
Data as JSON: /api/errors/bdfed8df05ebdf8a.
Report an issue: GitHub.