hashicorp/terraform · error

failed to create temp known_hosts file

Error message

failed to create temp known_hosts file: %s

What it means

This error occurs inside buildSSHClientConfig when Terraform's SSH provisioner tries to create a temporary file to hold the user-supplied host_key for known_hosts verification. The knownhosts package only accepts file paths, so Terraform writes the in-memory host key to a temp file via ioutil.TempFile. If the OS cannot create that temp file (permissions, disk full, exhausted inodes, invalid TMPDIR), the entire SSH connection setup aborts.

Solutions

  1. Verify the system temp directory is writable: run `echo $TMPDIR` (or check /tmp) and confirm the Terraform process user can create files there.
  2. Free disk space or increase the temp directory quota if the volume is full.
  3. If running in a container, mount /tmp as a writable tmpfs or volume with adequate size.
  4. Check open file descriptor limits (ulimit -n) and raise them if EMFILE is the underlying cause.
  5. If the environment temp dir is restricted, set TMPDIR to a writable location before invoking Terraform.

Example fix

# before (TMPDIR points to read-only path)
export TMPDIR=/readonly/tmp
terraform apply

# after
export TMPDIR=/var/tmp/tf-work
mkdir -p $TMPDIR
terraform apply
Defensive patterns

Strategy: validation

Validate before calling

// Before configuring the SSH connection, verify temp dir writability
import (
    "os"
    "path/filepath"
)

func checkTempDirWritable() error {
    f, err := os.CreateTemp("", "tf-precheck")
    if err != nil {
        return fmt.Errorf("temp directory not writable: %w", err)
    }
    f.Close()
    os.Remove(f.Name())
    return nil
}

// Call before provisioning:
// if err := checkTempDirWritable(); err != nil { log.Fatal(err) }

Prevention

When it happens

Trigger: Calling an SSH communicator with a non-empty host_key connection parameter, where ioutil.TempFile("", "tf-known_host") fails. Triggered by: read-only or missing system temp directory, ENOSPC (disk full), EMFILE (too many open files), or a TMPDIR environment variable pointing to a non-existent or unwritable path.

Common situations: Running Terraform in a hardened container or CI runner where /tmp is mounted read-only or has a noexec constraint with tight space limits. Setting TMPDIR to a path that doesn't exist. Running under a service account without write access to the default temp directory. Disk exhaustion on the worker node during a large provisioning run.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/c7e8969aaa7cdd6d. Report an issue: GitHub.

Appendix: source

Thrown at internal/communicator/ssh/provisioner.go:339

	password    string
	sshAgent    *sshAgent
	certificate string
	user        string
	host        string
	hostKey     string
}

func buildSSHClientConfig(opts sshClientConfigOpts) (*ssh.ClientConfig, error) {
	hkCallback := ssh.InsecureIgnoreHostKey()

	if opts.hostKey != "" {
		// The knownhosts package only takes paths to files, but terraform
		// generally wants to handle config data in-memory. Rather than making
		// the known_hosts file an exception, write out the data to a temporary
		// file to create the HostKeyCallback.
		tf, err := ioutil.TempFile("", "tf-known_hosts")
		if err != nil {
			return nil, fmt.Errorf("failed to create temp known_hosts file: %s", err)
		}
		defer tf.Close()
		defer os.RemoveAll(tf.Name())

		// we mark this as a CA as well, but the host key fallback will still
		// use it as a direct match if the remote host doesn't return a
		// certificate.
		if _, err := tf.WriteString(fmt.Sprintf("@cert-authority %s %s\n", opts.host, opts.hostKey)); err != nil {
			return nil, fmt.Errorf("failed to write temp known_hosts file: %s", err)
		}
		tf.Sync()

		hkCallback, err = knownhosts.New(tf.Name())
		if err != nil {
			return nil, err
		}
	}

View on GitHub (pinned to d32a084675)