{"record":{"id":"429eae90a2c14c29","repo":"hashicorp/terraform","slug":"error-connecting-to-bastion-s","errorCode":null,"errorMessage":"Error connecting to bastion: %s","messagePattern":"Error connecting to bastion: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/communicator/ssh/communicator.go","lineNumber":861,"sourceCode":"\t\t\tpConn, err = newHttpProxyConn(p, bAddr)\n\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"Error connecting to proxy: %s\", err)\n\t\t\t}\n\n\t\t\tbConn, bChans, bReq, err = ssh.NewClientConn(pConn, bAddr, bConf)\n\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"Error creating new client connection via proxy: %s\", err)\n\t\t\t}\n\n\t\t\tbastion = ssh.NewClient(bConn, bChans, bReq)\n\t\t} else {\n\t\t\tbastion, err = ssh.Dial(bProto, bAddr, bConf)\n\t\t}\n\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"Error connecting to bastion: %s\", err)\n\t\t}\n\n\t\tlog.Printf(\"[DEBUG] Connecting via bastion (%s) to host: %s\", bAddr, addr)\n\t\tconn, err := bastion.Dial(proto, addr)\n\t\tif err != nil {\n\t\t\tbastion.Close()\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// Wrap it up so we close both things properly\n\t\treturn &bastionConn{\n\t\t\tConn:    conn,\n\t\t\tBastion: bastion,\n\t\t}, nil\n\t}\n}\n\ntype bastionConn struct {","sourceCodeStart":843,"sourceCodeEnd":879,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/communicator/ssh/communicator.go#L843-L879","documentation":"Raised in BastionConnectFunc when ssh.Dial(bProto, bAddr, bConf) fails on the non-proxy path (no HTTP proxy configured). This is the direct SSH connection to the bastion host and covers both TCP connection failure and SSH handshake/auth failure to the bastion.","triggerScenarios":"When a bastion_host is set but no proxy is configured, the communicator dials the bastion directly via ssh.Dial. This error fires if the bastion is unreachable on the network, the SSH handshake fails, or bastion authentication fails.","commonSituations":"Wrong bastion_host or bastion_port, the bastion is behind a firewall/security group that blocks the terraform runner, bastion_user/bastion_private_key/bastion_password are incorrect, or the bastion sshd is not running.","solutions":["Verify bastion_host and bastion_port are correct and the bastion is reachable (nc -zv bastion 22).","Confirm bastion_user, bastion_private_key, and bastion_password are valid.","Check that the security group / firewall allows inbound SSH from the terraform runner's IP.","Ensure the bastion sshd service is running."],"exampleFix":"// before\nconnection {\n  bastion_host = var.bastion\n  user         = var.user\n}\n\n// after\nconnection {\n  bastion_host       = var.bastion\n  bastion_user       = var.user\n  bastion_private_key = file(\"~/.ssh/id_rsa\")\n  user               = var.user\n  private_key        = file(\"~/.ssh/id_rsa\")\n}","handlingStrategy":"retry","validationCode":"// Validate bastion reachability before provisioning\nfunc validateBastionReachable(bastionHost string, bastionPort uint16) error {\n    addr := fmt.Sprintf(\"%s:%d\", bastionHost, bastionPort)\n    conn, err := net.DialTimeout(\"tcp\", addr, 10*time.Second)\n    if err != nil {\n        return fmt.Errorf(\"cannot reach bastion %s: %w\", addr, err)\n    }\n    conn.Close()\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify the bastion security group/firewall allows SSH from the terraform runner IP.","Confirm bastion_user, bastion_private_key, and bastion_password are correct.","Use bastion_port explicitly if the bastion SSH runs on a non-standard port."],"tags":["ssh","bastion","network","authentication","terraform"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}