{"record":{"id":"c7e8969aaa7cdd6d","repo":"hashicorp/terraform","slug":"failed-to-create-temp-known-hosts-file-s","errorCode":null,"errorMessage":"failed to create temp known_hosts file: %s","messagePattern":"failed to create temp known_hosts file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/communicator/ssh/provisioner.go","lineNumber":339,"sourceCode":"\tpassword    string\n\tsshAgent    *sshAgent\n\tcertificate string\n\tuser        string\n\thost        string\n\thostKey     string\n}\n\nfunc buildSSHClientConfig(opts sshClientConfigOpts) (*ssh.ClientConfig, error) {\n\thkCallback := ssh.InsecureIgnoreHostKey()\n\n\tif opts.hostKey != \"\" {\n\t\t// The knownhosts package only takes paths to files, but terraform\n\t\t// generally wants to handle config data in-memory. Rather than making\n\t\t// the known_hosts file an exception, write out the data to a temporary\n\t\t// file to create the HostKeyCallback.\n\t\ttf, err := ioutil.TempFile(\"\", \"tf-known_hosts\")\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to create temp known_hosts file: %s\", err)\n\t\t}\n\t\tdefer tf.Close()\n\t\tdefer os.RemoveAll(tf.Name())\n\n\t\t// we mark this as a CA as well, but the host key fallback will still\n\t\t// use it as a direct match if the remote host doesn't return a\n\t\t// certificate.\n\t\tif _, err := tf.WriteString(fmt.Sprintf(\"@cert-authority %s %s\\n\", opts.host, opts.hostKey)); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to write temp known_hosts file: %s\", err)\n\t\t}\n\t\ttf.Sync()\n\n\t\thkCallback, err = knownhosts.New(tf.Name())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/communicator/ssh/provisioner.go#L321-L357","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the system temp directory is writable: run `echo $TMPDIR` (or check /tmp) and confirm the Terraform process user can create files there.","Free disk space or increase the temp directory quota if the volume is full.","If running in a container, mount /tmp as a writable tmpfs or volume with adequate size.","Check open file descriptor limits (ulimit -n) and raise them if EMFILE is the underlying cause.","If the environment temp dir is restricted, set TMPDIR to a writable location before invoking Terraform."],"exampleFix":"# before (TMPDIR points to read-only path)\nexport TMPDIR=/readonly/tmp\nterraform apply\n\n# after\nexport TMPDIR=/var/tmp/tf-work\nmkdir -p $TMPDIR\nterraform apply","handlingStrategy":"validation","validationCode":"// Before configuring the SSH connection, verify temp dir writability\nimport (\n    \"os\"\n    \"path/filepath\"\n)\n\nfunc checkTempDirWritable() error {\n    f, err := os.CreateTemp(\"\", \"tf-precheck\")\n    if err != nil {\n        return fmt.Errorf(\"temp directory not writable: %w\", err)\n    }\n    f.Close()\n    os.Remove(f.Name())\n    return nil\n}\n\n// Call before provisioning:\n// if err := checkTempDirWritable(); err != nil { log.Fatal(err) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["In CI containers, ensure /tmp is a writable tmpfs or volume with adequate free space.","Set TMPDIR explicitly to a known-writable path in your Terraform runner environment.","Monitor disk space on the runner to prevent ENOSPC during provisioning.","Raise ulimit -n if running many concurrent SSH connections."],"tags":["ssh","filesystem","temp-file","provisioner","infrastructure"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}