lbjlaq/Antigravity-Manager · error
brew_timeout
brew_timeout
Error message
brew_timeout
What it means
brew_upgrade_cask (src-tauri/src/modules/update_checker.rs) wraps the `brew upgrade --cask antigravity-tools` invocation in tokio::time::timeout with a 180-second budget. 'brew_timeout' is returned when the elapsed-time future resolves first, i.e. brew did not finish within 3 minutes and the child future is dropped. This is a safety guard so the UI does not hang forever on a stalled brew process.
Solutions
- Run `brew upgrade --cask antigravity-tools` manually in Terminal to see where it stalls and let it finish once; then retry the in-app upgrade (subsequent runs are usually faster since downloads are cached).
- Ensure no other brew process is running (`pgrep -fl brew`) that could hold the Homebrew lock; wait or kill stale processes.
- Pre-warm with `brew update` beforehand so the upgrade command skips the slow tap-update phase inside the 3-minute window.
- Check network/proxy speed to the cask download URL; use a faster connection or VPN off, then retry.
- If timeouts are chronic in your environment, run the upgrade manually and use the app after; the 3-minute timeout is hardcoded in update_checker.rs:510-516.
Example fix
// before: upgrade blocked by concurrent brew holding the lock, hits 180s timeout // terminal: pgrep -fl brew // finds stale brew process kill <stale_pid> brew update && brew upgrade --cask antigravity-tools // completes < 3 min // after: retry upgrade in app -> succeeds
Defensive patterns
Strategy: retry
Validate before calling
// Check for a concurrent brew process / lock before triggering the in-app upgrade
const { exec } = require('child_process');
exec('pgrep -fl brew', (err, stdout) => {
if (stdout && stdout.trim()) console.warn('another brew process is running; upgrade may time out');
}); Try / catch
let ok = false;
for (let i = 0; i < 2 && !ok; i++) {
try { await invoke('brew_upgrade_cask'); ok = true; }
catch (e) {
if (e !== 'brew_timeout') throw e;
showHint('brew is slow (network/lock). Ensure no other brew run is active, then retry.');
}
} Prevention
- Run `brew update` ahead of time so the 3-minute window is spent only on the actual upgrade.
- Don't run other brew commands concurrently with the in-app upgrade.
- Upgrade on a fast, unproxied connection; large cask downloads can exceed 180s.
- If the machine is slow (CI/VM), perform the upgrade manually in Terminal where there is no timeout.
- Retry once after a timeout — cached downloads usually make the second attempt finish quickly.
When it happens
Trigger: tokio::time::timeout(Duration::from_secs(180), brew_command.output()) returns Err — brew ran longer than 3 minutes, typically because it was updating itself/other casks, downloading slowly, prompting, waiting on a lock, or hung on network access to formulae.brew.sh or the cask download host.
Common situations: Slow or proxied internet making the cask download exceed 3 minutes; concurrent brew operations holding the Homebrew lock (another Terminal brew run); brew auto-updating its own tap first (`brew update` phase); a stuck sudo/prompt-less network credential dialog; heavily loaded CI/VM.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- brew_already_latest
- brew_exec_failed
- brew_upgrade_failed
- Keyring write timed out (10s). The D-Bus session bus is not…
AI-assisted analysis of lbjlaq/Antigravity-Manager@90a2b6b207 (2026-09-19).
Data as JSON: /api/errors/5801483defedd6de.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/src/modules/update_checker.rs:526
// 3 min timeout to prevent hanging
let result = tokio::time::timeout(
std::time::Duration::from_secs(180),
tokio::process::Command::new(brew_path)
.args(["upgrade", "--cask", "antigravity-tools"])
.output(),
)
.await;
let output = match result {
Ok(Ok(output)) => output,
Ok(Err(e)) => {
logger::log_error(&format!("Failed to execute brew upgrade: {}", e));
return Err("brew_exec_failed".to_string());
}
Err(_) => {
logger::log_error("Homebrew upgrade timed out after 3 minutes");
return Err("brew_timeout".to_string());
}
};
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
let stderr = String::from_utf8_lossy(&output.stderr).to_string();
if output.status.success() {
logger::log_info(&format!("Homebrew upgrade succeeded: {}", stdout));
Ok(stdout)
} else {
logger::log_error(&format!(
"brew upgrade failed - stdout: {} stderr: {}",
stdout, stderr
));
// Return structured error key for frontend i18n
if stderr.contains("already installed") || stdout.contains("already installed") {
Err("brew_already_latest".to_string())
} else {View on GitHub (pinned to 90a2b6b207)