hashicorp/terraform · error

Error connecting to bastion: %s

Error message

Error connecting to bastion: %s

What it means

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.

Source

Thrown at internal/communicator/ssh/communicator.go:861

			pConn, err = newHttpProxyConn(p, bAddr)

			if err != nil {
				return nil, fmt.Errorf("Error connecting to proxy: %s", err)
			}

			bConn, bChans, bReq, err = ssh.NewClientConn(pConn, bAddr, bConf)

			if err != nil {
				return nil, fmt.Errorf("Error creating new client connection via proxy: %s", err)
			}

			bastion = ssh.NewClient(bConn, bChans, bReq)
		} else {
			bastion, err = ssh.Dial(bProto, bAddr, bConf)
		}

		if err != nil {
			return nil, fmt.Errorf("Error connecting to bastion: %s", err)
		}

		log.Printf("[DEBUG] Connecting via bastion (%s) to host: %s", bAddr, addr)
		conn, err := bastion.Dial(proto, addr)
		if err != nil {
			bastion.Close()
			return nil, err
		}

		// Wrap it up so we close both things properly
		return &bastionConn{
			Conn:    conn,
			Bastion: bastion,
		}, nil
	}
}

type bastionConn struct {

View on GitHub (pinned to c9def3e214)

Solutions

  1. Verify bastion_host and bastion_port are correct and the bastion is reachable (nc -zv bastion 22).
  2. Confirm bastion_user, bastion_private_key, and bastion_password are valid.
  3. Check that the security group / firewall allows inbound SSH from the terraform runner's IP.
  4. Ensure the bastion sshd service is running.

Example fix

// before
connection {
  bastion_host = var.bastion
  user         = var.user
}

// after
connection {
  bastion_host       = var.bastion
  bastion_user       = var.user
  bastion_private_key = file("~/.ssh/id_rsa")
  user               = var.user
  private_key        = file("~/.ssh/id_rsa")
}
Defensive patterns

Strategy: retry

Validate before calling

// Validate bastion reachability before provisioning
func validateBastionReachable(bastionHost string, bastionPort uint16) error {
    addr := fmt.Sprintf("%s:%d", bastionHost, bastionPort)
    conn, err := net.DialTimeout("tcp", addr, 10*time.Second)
    if err != nil {
        return fmt.Errorf("cannot reach bastion %s: %w", addr, err)
    }
    conn.Close()
    return nil
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/429eae90a2c14c29. Report an issue: GitHub.