chenhg5/cc-connect · warning
xdg-open not found (headless server?): %w
Error message
xdg-open not found (headless server?): %w
What it means
openBrowser, used by `cc-connect web` (runWeb), opens the dashboard URL in a browser. On Linux it first looks up xdg-open via exec.LookPath; when missing it returns "xdg-open not found (headless server?)" instead of silently failing to start a browser. The web server itself still runs — the caller is expected to print the URL so the user can open it remotely.
Source
Thrown at cmd/cc-connect/web.go:92
fmt.Printf("\nCould not open browser automatically.\n")
fmt.Printf("Open this URL in your browser:\n")
fmt.Printf(" %s/login?token=%s\n", baseURL, token)
fmt.Printf("\nNote: make sure cc-connect is running (it hosts the web admin on port %d).\n", port)
}
}
func openBrowser(rawURL string) error {
switch runtime.GOOS {
case "darwin":
return exec.Command("open", rawURL).Start()
case "linux":
if isWSL() {
return exec.Command("cmd.exe", "/c", "start", rawURL).Start()
}
// On headless Linux, xdg-open is often unavailable.
// Check early and return a clear error so the caller can print the URL.
if _, err := exec.LookPath("xdg-open"); err != nil {
return fmt.Errorf("xdg-open not found (headless server?): %w", err)
}
return exec.Command("xdg-open", rawURL).Start()
case "windows":
return exec.Command("cmd", "/c", "start", rawURL).Start()
default:
return fmt.Errorf("unsupported OS: %s", runtime.GOOS)
}
}
func isWSL() bool {
data, err := os.ReadFile("/proc/version")
if err != nil {
return false
}
return strings.Contains(strings.ToLower(string(data)), "microsoft")
}
View on GitHub (pinned to 4000b2338a)
Solutions
- Open the printed URL manually in your local browser — the web server is running regardless.
- Install xdg-utils (apt install xdg-utils / dnf install xdg-utils) if the machine actually has a desktop.
- Set $BROWSER to a usable browser or script so the opener has a target.
- If connecting remotely, use SSH port forwarding: ssh -L 8080:localhost:8080 user@host, then browse http://localhost:8080.
- On WSL, verify /proc/version is readable so isWSL() can route to cmd.exe /c start instead of xdg-open.
Example fix
// before cc-connect web # on headless server: xdg-open not found // after cc-connect web # copy the printed URL, or: ssh -L 8080:localhost:8080 user@server
Defensive patterns
Strategy: fallback
Validate before calling
if _, err := exec.LookPath("xdg-open"); err != nil {
fmt.Println("No browser available; open the URL manually:", url)
} Try / catch
if err := openBrowser(url); err != nil {
var notFoundErr *exec.Error
if errors.As(err, ¬FoundErr) || strings.Contains(err.Error(), "xdg-open not found") {
fmt.Println("Web UI running at:", url) // print URL instead of failing
}
} Prevention
- Install xdg-utils on desktop Linux machines
- Set $BROWSER in headless/CI environments
- Expect the URL to be printed on headless servers and open it locally
- Use SSH port forwarding for remote dashboards
When it happens
Trigger: Running `cc-connect web` (which calls openBrowser) on a Linux machine without xdg-open in PATH — typically headless servers, containers, SSH sessions without a desktop environment, or minimal distro images lacking xdg-utils.
Common situations: Starting the web dashboard on a VPS or Docker container; SSH-ing into a CI box; a slim Debian/Alpine image without the xdg-utils package.
Related errors
- unsupported OS: %s
- systemctl not found: systemd is required on Linux; if runnin
- systemd is not active (state: %s). If running in a contain
- systemd check failed (state: %s). Use nohup as alternative
- systemd user session not available. This often happens whe
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/67c36a1600a78d5e.
Report an issue: GitHub.