{"record":{"id":"6f38e12b19a56551","repo":"cli/cli","slug":"error-getting-tunnel-client-w","errorCode":null,"errorMessage":"error getting tunnel client: %w","messagePattern":"error getting tunnel client: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/codespaces/connection/connection.go","lineNumber":75,"sourceCode":"\tmanagementToken := tunnelProperties.ManagePortsAccessToken\n\n\t// Create the tunnel definition\n\ttunnel := &tunnels.Tunnel{\n\t\tAccessTokens: map[tunnels.TunnelAccessScope]string{tunnels.TunnelAccessScopeConnect: connectToken, tunnels.TunnelAccessScopeManagePorts: managementToken},\n\t\tTunnelID:     tunnelProperties.TunnelId,\n\t\tClusterID:    tunnelProperties.ClusterId,\n\t\tDomain:       tunnelProperties.Domain,\n\t}\n\n\t// Create options\n\toptions := &tunnels.TunnelRequestOptions{\n\t\tIncludePorts: true,\n\t}\n\n\t// Create the tunnel client (not connected yet)\n\ttunnelClient, err := getTunnelClient(ctx, tunnelManager, tunnel, options)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting tunnel client: %w\", err)\n\t}\n\n\treturn &CodespaceConnection{\n\t\ttunnelProperties:           tunnelProperties,\n\t\tTunnelManager:              tunnelManager,\n\t\tTunnelClient:               tunnelClient,\n\t\tOptions:                    options,\n\t\tTunnel:                     tunnel,\n\t\tAllowedPortPrivacySettings: allowedPortPrivacySettings,\n\t}, nil\n}\n\n// Connect connects the client to the tunnel.\nfunc (c *CodespaceConnection) Connect(ctx context.Context) error {\n\t// Lock the mutex to prevent race conditions with the underlying SSH connection\n\tc.TunnelClient.mu.Lock()\n\tdefer c.TunnelClient.mu.Unlock()\n","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/cli/cli/blob/0eeec0b92edbe70199f9768522f831d3534f41ad/internal/codespaces/connection/connection.go#L57-L93","documentation":"Thrown by NewCodespaceConnection when getTunnelClient fails, i.e. tunnelManager.CreateTunnel / the tunnel-client creation step (via the microsoft/dev-tunnels SDK) errors while setting up the SSH-based tunnel client for the codespace. This talks to the dev-tunnels service using the Connect/ManagePorts access tokens from the codespace's TunnelProperties.","triggerScenarios":"Connecting to a codespace where the tunnel service rejects the request: expired/invalid tunnel access tokens, tunnel not found on the cluster (tunnel already torn down), dev-tunnels service outage, or network failure reaching the tunnel service URI.","commonSituations":"Long-lived codespace records whose tunnel tokens expired; codespace shut down/deleted concurrently; dev-tunnels service incidents; restrictive networks blocking the tunnel endpoints (non-GitHub hosts, which is why the credential-free ExternalHTTPClient is used).","solutions":["Stop and restart the codespace (gh codespace stop then connect again) to mint fresh tunnel tokens.","Retry after a dev-tunnels service incident; check status indicators for GitHub Codespaces.","Ensure the network allows traffic to the tunnel service host in TunnelProperties.ServiceUri (often *.tunnels.api.visualstudio.com or regional equivalents).","If tokens are persistently invalid, delete and recreate the codespace."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"conn, err := connection.NewCodespaceConnection(ctx, cs, httpClient)\nif err != nil && strings.Contains(err.Error(), \"error getting tunnel client\") {\n    // tunnel tokens may be stale: stop/start the codespace, then retry once\n    _ = apiClient.StopCodespace(ctx, cs.Name)\n    time.Sleep(10 * time.Second)\n    conn, err = connection.NewCodespaceConnection(ctx, cs, httpClient)\n}","preventionTips":["Restart the codespace when tunnel tokens are rejected to mint new ones.","Allow outbound access to the dev-tunnels relay hosts in firewall rules.","Retry with backoff during suspected tunnel service incidents."],"tags":["go","codespaces","dev-tunnels","auth-token","network"],"backgroundTag":null,"analyzedSha":"0eeec0b92edbe70199f9768522f831d3534f41ad","analyzedAt":"2026-08-15T12:31:05.478Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}