cli/cli · warning
failed to open JupyterLab in browser: %w
Error message
failed to open JupyterLab in browser: %w
What it means
Raised by gh codespace jupyter when a.browser.Browse(targetUrl) fails to open the constructed JupyterLab URL in the user's browser. The targetUrl is derived from the server-reported URL with the server port replaced by the local forwarded port, and it embeds Jupyter's authentication token, which must survive the rewrite. The failure is purely local: no valid browser/launcher could be spawned for this URL.
Source
Thrown at pkg/cmd/codespace/jupyter.go:94
if err != nil {
return err
}
defer listen.Close()
destPort := listen.Addr().(*net.TCPAddr).Port
tunnelClosed := make(chan error, 1)
go func() {
opts := portforwarder.ForwardPortOpts{
Port: serverPort,
}
tunnelClosed <- fwd.ForwardPortToListener(ctx, opts, listen)
}()
// Server URL contains an authentication token that must be preserved
targetUrl := strings.Replace(serverUrl, fmt.Sprintf("%d", serverPort), fmt.Sprintf("%d", destPort), 1)
err = a.browser.Browse(targetUrl)
if err != nil {
return fmt.Errorf("failed to open JupyterLab in browser: %w", err)
}
fmt.Fprintln(a.io.Out, targetUrl)
select {
case err := <-tunnelClosed:
return fmt.Errorf("tunnel closed: %w", err)
case <-ctx.Done():
return nil // success
}
}
View on GitHub (pinned to 0eeec0b92e)
Solutions
- If on a headless/remote machine, set BROWSER to a no-op or run with a mechanism that prints the URL instead (e.g. use `gh codespace jupyter` locally, or copy the printed URL manually after starting)
- Check the BROWSER environment variable: unset it or point it to a real executable (`echo $BROWSER`)
- On Linux ensure xdg-open exists (install xdg-utils); on WSL ensure wslview/browser integration is set up
- Inspect targetUrl in the error chain for oddities - a malformed serverUrl (e.g. port number appearing in host) can break the string port replacement
Example fix
// before: headless host fails to spawn a browser export BROWSER=/nonexistent gh codespace jupyter // after: print-only on headless hosts, open locally by hand export BROWSER=echo # gh prints the URL (token included) instead of failing
Defensive patterns
Strategy: fallback
Validate before calling
// Check a browser is actually spawnable before starting the tunnel work
if browser := os.Getenv("BROWSER"); browser != "" {
if _, err := exec.LookPath(strings.Fields(browser)[0]); err != nil { /* will fail; set BROWSER=echo */ }
} Try / catch
// Fallback: if Browse fails, degrade to printing the URL (token included) instead of erroring
if err := a.browser.Browse(targetUrl); err != nil {
fmt.Fprintf(a.io.ErrOut, "could not open browser: %v\n", err)
fmt.Fprintln(a.io.Out, targetUrl) // user opens manually
} Prevention
- On headless hosts set BROWSER=echo so gh prints the URL
- Keep xdg-utils installed on Linux desktops
- In SSH sessions, prefer running gh locally or copy the printed URL
- Never strip the token from the URL when copying it manually
When it happens
Trigger: Running `gh codespace jupyter` in an environment where no browser can be opened: headless server or container with no display, SSH session without X forwarding, BROWSER env var pointing at a nonexistent executable, or an OS where the xdg-open/open mechanism fails.
Common situations: Running gh over SSH to a remote box (no GUI); CI containers; WSL without a Windows browser bridge configured; BROWSER set to a broken script; unusual desktop environments lacking xdg-open.
Related errors
- remote command: %w
- error editing codespace: %w
- error connecting to codespace: %w
- failed to create port forwarder: %w
- tunnel closed: %w
AI-assisted analysis of cli/cli@0eeec0b92e (2026-08-15).
Data as JSON: /api/errors/2fb485e95e851fe4.
Report an issue: GitHub.