{"record":{"id":"ea4bde6c1db4e012","repo":"hashicorp/terraform","slug":"error-reading-error-message-s","errorCode":null,"errorMessage":"Error reading error message: %s","messagePattern":"Error reading error message: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/communicator/ssh/communicator.go","lineNumber":638,"sourceCode":"\t}\n\n\treturn nil\n}\n\n// checkSCPStatus checks that a prior command sent to SCP completed\n// successfully. If it did not complete successfully, an error will\n// be returned.\nfunc checkSCPStatus(r *bufio.Reader) error {\n\tcode, err := r.ReadByte()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif code != 0 {\n\t\t// Treat any non-zero (really 1 and 2) as fatal errors\n\t\tmessage, _, err := r.ReadLine()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"Error reading error message: %s\", err)\n\t\t}\n\n\t\treturn errors.New(string(message))\n\t}\n\n\treturn nil\n}\n\nvar testUploadSizeHook func(size int64)\n\nfunc scpUploadFile(dst string, src io.Reader, w io.Writer, r *bufio.Reader, size int64) error {\n\tif testUploadSizeHook != nil {\n\t\ttestUploadSizeHook(size)\n\t}\n\n\tif size == 0 {\n\t\t// Create a temporary file where we can copy the contents of the src\n\t\t// so that we can determine the length, since SCP is length-prefixed.","sourceCodeStart":620,"sourceCodeEnd":656,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/communicator/ssh/communicator.go#L620-L656","documentation":"Emitted by checkSCPStatus when an SCP error indicator byte was received from the remote but the subsequent error line could not be read with r.ReadLine(). The remote signalled failure (non-zero status byte) yet the connection broke before the human-readable error message arrived, so only the wrapped read error is reported.","triggerScenarios":"The SCP sub-protocol exchanged a fatal code then the underlying connection dropped or timed out before the message bytes arrived. Common with the remote scp binary crashing, a proxy/bastion severing the link, or a slow link where the read blocks past the timeout.","commonSituations":"Bastion/proxy instability mid-transfer; remote scp not installed or wrong variant (busybox vs OpenBSD scp) sending unexpected output; aggressive idle timeout on a load balancer.","solutions":["Re-run the apply; SCP transfers are retried within the connection timeout.","Confirm scp is installed on the target and is the OpenSSH variant (busybox scp has known incompatibilities).","Stabilize the bastion/proxy path; increase connection.timeout for slow links.","For repeated failures, upload smaller files or use file provisioner with a local-exec alternative."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// In Go, SCP read errors after a fatal status byte are usually transient;\n// retry the upload within the connection timeout, then fail with context:\nif strings.Contains(err.Error(), \"Error reading error message\") {\n    if attempt < maxAttempts { time.Sleep(backoff); continue }\n    return fmt.Errorf(\"scp transfer failed and remote error was lost: %w\", err)\n}","preventionTips":["Confirm OpenSSH scp (not busybox) is installed on the target.","Stabilize bastion/proxy paths used during uploads.","Keep individual file sizes small to reduce transfer-time failure surface."],"tags":["terraform","ssh","scp","upload","io","provisioner"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}