From c8742badbbeb13849c4cf0f20a7f15a90a61a172 Mon Sep 17 00:00:00 2001 From: Kacper Sawicki Date: Thu, 25 Sep 2025 12:03:51 +0200 Subject: [PATCH] fix(cli): enhance error handling for multiple agents in SSH command (#19943) Closes #19812 ## Problem > When I try to SSH into my workspace with multiple agents. It does not provide an intuitive way to do that successfully and instead misguides by printing wrong instructions. This PR enhances the error handling to provide suggestions with SSH commands that users can copy and paste directly. Before: ``` Encountered an error running "coder ssh", see "coder ssh --help" for more information error: multiple agents found, please specify the agent name, available agents: [coder dev] ``` After: ``` Encountered an error running "coder ssh", see "coder ssh --help" for more information error: multiple agents found, please specify the agent name, available agents: [coder dev] Try running: $ ssh coder.dogfood.me.coder $ ssh dev.dogfood.me.coder ``` --- cli/ssh.go | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/cli/ssh.go b/cli/ssh.go index 609670b690..323d2913ae 100644 --- a/cli/ssh.go +++ b/cli/ssh.go @@ -756,7 +756,23 @@ func findWorkspaceAndAgentByHostname( hostname = strings.TrimSuffix(hostname, qualifiedSuffix) } hostname = normalizeWorkspaceInput(hostname) - ws, agent, _, err := GetWorkspaceAndAgent(ctx, inv, client, !disableAutostart, hostname) + + ws, agent, otherAgents, err := GetWorkspaceAndAgent(ctx, inv, client, !disableAutostart, hostname) + if err != nil && strings.Contains(err.Error(), "multiple agents found") { + var errorMsg strings.Builder + _, _ = errorMsg.WriteString(fmt.Sprintf("%s\nTry running:\n", err.Error())) + for _, agent := range otherAgents { + switch { + case config.HostnameSuffix != "": + _, _ = errorMsg.WriteString(fmt.Sprintf(" %s\n", cliui.Code(fmt.Sprintf("$ ssh %s.%s.%s.%s", agent.Name, ws.Name, ws.OwnerName, config.HostnameSuffix)))) + case config.HostnamePrefix != "": + _, _ = errorMsg.WriteString(fmt.Sprintf(" %s\n", cliui.Code(fmt.Sprintf("$ ssh %s%s.%s.%s", config.HostnamePrefix, agent.Name, ws.Name, ws.OwnerName)))) + default: + _, _ = errorMsg.WriteString(fmt.Sprintf(" %s\n", cliui.Code(fmt.Sprintf("$ ssh %s.%s.%s", agent.Name, ws.Name, ws.OwnerName)))) + } + } + return ws, agent, xerrors.New(errorMsg.String()) + } return ws, agent, err } @@ -922,7 +938,7 @@ func GetWorkspaceAndAgent(ctx context.Context, inv *serpent.Invocation, client * } workspaceAgent, otherWorkspaceAgents, err := getWorkspaceAgent(workspace, agentName) if err != nil { - return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, nil, err + return workspace, codersdk.WorkspaceAgent{}, otherWorkspaceAgents, err } return workspace, workspaceAgent, otherWorkspaceAgents, nil @@ -958,7 +974,7 @@ func getWorkspaceAgent(workspace codersdk.Workspace, agentName string) (workspac if len(agents) == 1 { return agents[0], nil, nil } - return codersdk.WorkspaceAgent{}, nil, xerrors.Errorf("multiple agents found, please specify the agent name, available agents: %v", availableNames) + return codersdk.WorkspaceAgent{}, agents, xerrors.Errorf("multiple agents found, please specify the agent name, available agents: %v", availableNames) } // Attempt to poll workspace autostop. We write a per-workspace lockfile to