alibaba/open-code-review · error

no browser opener available

Error message

no browser opener available

What it means

openBrowserCandidates tries each configured browser opener command; if the candidate list is empty, it throws 'no browser opener available'. If candidates existed but all failed, it instead joins their per-command errors — this specific error means nothing was ever attempted.

Source

Thrown at internal/viewer/browser.go:221

func openBrowser(url string) error {
	return openBrowserCandidates(browserCandidates(runtime.GOOS, os.Getenv("BROWSER"), url))
}

// openBrowserCandidates tries each candidate in turn. Every failure is reported,
// not just the first: with $BROWSER set to something uninstalled and no platform
// opener present either, hearing only about $BROWSER would suggest fixing that
// variable is enough.
func openBrowserCandidates(candidates [][]string) error {
	var errs []error
	for _, argv := range candidates {
		err := runBrowserCmd(exec.Command(argv[0], argv[1:]...))
		if err == nil {
			return nil
		}
		errs = append(errs, fmt.Errorf("%s: %w", argv[0], err))
	}
	if len(errs) == 0 {
		return errors.New("no browser opener available")
	}
	return errors.Join(errs...)
}

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Install a browser opener, e.g. apt-get install xdg-utils on Debian/Ubuntu containers.
  2. Ensure the opener binary is on PATH (echo $PATH; which xdg-open).
  3. Open the viewer URL manually and print it instead of relying on browser auto-open in headless environments.
  4. On macOS/Windows verify platform detection is not misclassifying the OS so the right opener is added to candidates.

Example fix

// before
// headless CI: openBrowser() -> no browser opener available
fmt.Println(url) // print instead
// after
// on the host/container:
sudo apt-get install -y xdg-utils
xdg-open http://127.0.0.1:PORT/...
Defensive patterns

Strategy: fallback

Validate before calling

function hasBrowserOpener() {
  const candidates = process.platform === 'darwin' ? ['open']
    : process.platform === 'win32' ? ['cmd']
    : ['xdg-open'];
  return candidates.some(c => { try { require('child_process').execSync(`command -v ${c}`, {stdio:'ignore'}); return true; } catch { return false; } });
}

Try / catch

url, err := viewer.Open(...)
if err != nil {
    if errors.Is(err, errNoBrowser) || strings.Contains(err.Error(), "no browser opener") {
        fmt.Println("Open manually:", url)
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: Calling openBrowser (via viewer functionality) on a platform where no known browser opener binary (e.g. xdg-open, open, cmd start variants) was found to build the candidate list.

Common situations: Minimal/headless Linux containers or CI with no xdg-open installed; stripped-down Docker images; PATH missing standard system directories; unusual platforms with no recognized opener.

Related errors


AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02). Data as JSON: /api/errors/2b0570e12f549a9e. Report an issue: GitHub.