cli/cli · error
tunnel closed: %w
Error message
tunnel closed: %w
What it means
Reported by gh codespace jupyter when the port-forward tunnel to the codespace terminates with an error. The tunnel goroutine runs fwd.ForwardPortToListener(ctx, opts, listen) and sends its result on tunnelClosed; receiving an error there means the websocket tunnel relaying the local listener to the codespace port died or failed to start forwarding. It is distinct from ctx.Done() on the same select, which is the normal shutdown path.
Source
Thrown at pkg/cmd/codespace/jupyter.go:101
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
- Simply rerun `gh codespace jupyter` - transient tunnel drops are the most common cause
- Check the codespace is still running: `gh codespace list` (state should be Running, not Shutdown/Deleted)
- If drops are frequent on your network, keep the session active or adjust idle timeout: `gh codespace edit -m ... --idle-timeout` / org policy
- Read the wrapped %w error: 'context canceled' during intentional shutdown is benign; websocket 1006/close errors point to network or relay issues
Defensive patterns
Strategy: try-catch
Try / catch
// Distinguish intentional shutdown from real tunnel failure
select {
case err := <-tunnelClosed:
if errors.Is(err, context.Canceled) { return nil } // normal shutdown
return fmt.Errorf("tunnel closed: %w", err)
case <-ctx.Done():
return nil
} Prevention
- Treat tunnel drops during long sessions as expected; re-run the command
- Keep the codespace active (raise idle timeout) for long browser sessions
- Avoid network switches/sleep while the jupyter session is open
- Check codespace state after a drop before assuming client-side bugs
When it happens
Trigger: `gh codespace jupyter` running with the browser open, then the tunnel drops: codespace stopped or deleted mid-session, network interruption killing the websocket, relay server closing the connection, or ForwardPortToListener failing immediately (e.g. the codespace port not listening yet inside the container).
Common situations: Laptop sleep/resume or Wi-Fi change dropping the tunnel; the codespace auto-stopping after idle timeout; Jupyter server process dying inside the codespace; flaky corporate networks that idle-out long-lived websockets.
Related errors
- failed to create port forwarder: %w
- failed to create port forwarder: %w
- failed to create port forwarder: %w
- failed to create port forwarder: %w
- connection closed: %w
AI-assisted analysis of cli/cli@0eeec0b92e (2026-08-15).
Data as JSON: /api/errors/4f4793c9e422b377.
Report an issue: GitHub.