router-for-me/CLIProxyAPI · warning
failed to start browser command: %w
Error message
failed to start browser command: %w
What it means
A browser command was selected, but cmd.Start() failed to spawn it. Unlike the lookup failure (error 297), the binary exists on PATH; the exec itself failed — permission denied, broken launcher script, missing dynamic library, or resource limits.
Source
Thrown at internal/browser/browser.go:74
// Try common Linux browsers in order of preference
browsers := []string{"xdg-open", "x-www-browser", "www-browser", "firefox", "chromium", "google-chrome"}
for _, browser := range browsers {
if _, err := exec.LookPath(browser); err == nil {
cmd = exec.Command(browser, url)
break
}
}
if cmd == nil {
return fmt.Errorf("no suitable browser found on Linux system")
}
default:
return fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
}
log.Debugf("Running command: %s %v", cmd.Path, cmd.Args[1:])
err := cmd.Start()
if err != nil {
return fmt.Errorf("failed to start browser command: %w", err)
}
log.Debug("Successfully opened URL using platform-specific command")
return nil
}
// IsAvailable checks if the system has a command available to open a web browser.
// It verifies the presence of necessary commands for the current operating system.
//
// Returns:
// - true if a browser can be opened, false otherwise.
func IsAvailable() bool {
// First check if open-golang can work
testErr := open.Run("about:blank")
if testErr == nil {
return true
}
View on GitHub (pinned to 78f0c4079e)
Solutions
- Check the wrapped error — exec.ErrNotFound vs permission denied vs library error point to different fixes
- For headless use, run with --no-browser and open the printed verification URI manually
- Reinstall/repair the launcher package (xdg-utils) or the browser if its binary is broken
- Set DISPLAY/WAYLAND_DISPLAY correctly when a GUI session exists
Example fix
# before $ cli-proxy-api --login # error: failed to start browser command: exec: ... (no DISPLAY) # after $ cli-proxy-api --login --no-browser # then open the printed URL on any machine with a browser
Defensive patterns
Strategy: fallback
Validate before calling
if !browser.IsAvailable() {
log.Infof("browser unavailable; open manually: %s", url)
return nil
} Try / catch
if err := browser.OpenURL(url); err != nil {
log.Warnf("browser launch failed (%v); open manually: %s", err, url)
// non-fatal: OAuth continues via the printed URL
} Prevention
- Treat browser launch failure as non-fatal: always print the URL as the fallback path
- Ensure DISPLAY/WAYLAND_DISPLAY is set in GUI sessions and xdg-utils is intact
- Use --no-browser on headless hosts instead of relying on a broken launcher
When it happens
Trigger: xdg-open exists but errors out immediately (broken .desktop handling, no DISPLAY under X11, exec format error), or a found binary lacks execute permission or its shared libraries.
Common situations: Headless session with no DISPLAY/WAYLAND_DISPLAY where GUI browsers fail to start; damaged xdg-utils install; containers with a browser binary but missing libs; PATH shims that shadow a real browser with a non-executable file.
Related errors
- no suitable browser found on Linux system
- missing access_token and refresh_token
- refresh response did not include access_token
- failed to save refreshed auth: %w
- antigravity token exchange: create request: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/85aeb246774b7cfa.
Report an issue: GitHub.