hashicorp/terraform · error
ssh client is not connected
Error message
ssh client is not connected
What it means
Returned by Communicator.newSession (communicator.go:522). When a SCP/SSH command is requested but c.client (the *ssh.Client) is nil — the connection was never established or was torn down — newSession returns this error. Notably it then immediately attempts c.Connect(nil) to reconnect and retries c.client.NewSession(); the caller only sees this message if that reconnect also fails to set up a session.
Source
Thrown at internal/communicator/ssh/communicator.go:522
if src[len(src)-1] != '/' {
log.Printf("[DEBUG] No trailing slash, creating the source directory name")
return scpUploadDirProtocol(filepath.Base(src), w, r, uploadEntries)
}
// Trailing slash, so only upload the contents
return uploadEntries()
}
cmd, err := quoteScpCommand([]string{"scp", "-rvt", dst}, c.connInfo.TargetPlatform)
if err != nil {
return err
}
return c.scpSession(cmd, scpFunc)
}
func (c *Communicator) newSession() (session *ssh.Session, err error) {
log.Println("[DEBUG] opening new ssh session")
if c.client == nil {
err = errors.New("ssh client is not connected")
} else {
session, err = c.client.NewSession()
}
if err != nil {
log.Printf("[WARN] ssh session open error: '%s', attempting reconnect", err)
if err := c.Connect(nil); err != nil {
return nil, err
}
return c.client.NewSession()
}
return session, nil
}
func (c *Communicator) scpSession(scpCommand string, f func(io.Writer, *bufio.Reader) error) error {
session, err := c.newSession()View on GitHub (pinned to c9def3e214)
Solutions
- Verify connectivity: ensure the host/port are reachable and credentials (connection block: host, port, private_key/password) are correct.
- For bastion/relay setups, confirm the bastion is reachable and the ProxyJump/bastion_host config is valid.
- Increase retries or add a depends_on so the resource network is up before the provisioner runs; check that Connect() succeeds by testing `ssh <host>` manually.
Example fix
# before
resource "null_resource" "x" {
provisioner "file" { # client nil if host not ready
connection { type = "ssh" host = aws_instance.w.public_ip }
}
}
# after: ensure instance/network are ready first
resource "null_resource" "x" {
depends_on = [aws_internet_gateway.main, aws_instance.w]
provisioner "file" {
connection {
type = "ssh"
host = aws_instance.w.public_ip
private_key = file("~/.ssh/id_rsa")
}
}
} Defensive patterns
Strategy: retry
Validate before calling
// Validate connection config and reachability before the provisioner runs.
if conn.Host == "" || !reachable(conn.Host, conn.Port) {
return errors.New("ssh target not reachable; fix connection block / network")
} Try / catch
// newSession already reconnects on failure; wrap caller logic to retry once.
err := communicator.Upload(dst, src)
if err != nil && strings.Contains(err.Error(), "not connected") {
if cerr := communicator.Connect(nil); cerr == nil {
err = communicator.Upload(dst, src)
}
} Prevention
- Use depends_on so the instance/network/bastion are ready before the provisioner runs.
- Validate the connection block (host, port, private_key/password, bastion) against a manual ssh test.
When it happens
Trigger: A provisioner (connection { type="ssh" }) tries to upload a file / run a command before Connect() succeeded, or after the underlying SSH connection dropped and the auto-reconnect in newSession could not re-establish it.
Common situations: Remote host unreachable / wrong port; SSH key auth failed so client stayed nil; connection idle-timed out and reconnect failed; provisioner ran before bastion/networking was ready.
Related errors
- connection type '%s' not supported
- SSH authentication failed (%s@%s): %w
- SCP failed to start. This usually means that SCP is not prop
- Failed to read ssh private key: no key found
- Failed to read ssh private key: password protected keys are
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/f646c9800603d4fa.
Report an issue: GitHub.