{"record":{"id":"c2aa550abe28b2a4","repo":"hashicorp/terraform","slug":"upload-failed-v","errorCode":null,"errorMessage":"Upload failed: %v","messagePattern":"Upload failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/builtin/provisioners/file/resource_provisioner.go","lineNumber":188,"sourceCode":"\t\treturn err\n\t}\n\n\t// disconnect when the context is canceled, which will close this after\n\t// Apply as well.\n\tgo func() {\n\t\t<-ctx.Done()\n\t\tcomm.Disconnect()\n\t}()\n\n\tinfo, err := os.Stat(src)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// If we're uploading a directory, short circuit and do that\n\tif info.IsDir() {\n\t\tif err := comm.UploadDir(dst, src); err != nil {\n\t\t\treturn fmt.Errorf(\"Upload failed: %v\", err)\n\t\t}\n\t\treturn nil\n\t}\n\n\t// We're uploading a file...\n\tf, err := os.Open(src)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer f.Close()\n\n\terr = comm.Upload(dst, f)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"Upload failed: %v\", err)\n\t}\n\n\treturn err\n}","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/builtin/provisioners/file/resource_provisioner.go#L170-L206","documentation":"Returned by copyFiles in the file provisioner at resource_provisioner.go:188 when comm.UploadDir(dst, src) fails while uploading a directory to a remote resource over the configured communicator (SSH/WinRM). The %v is the raw communicator error. This fires only after a connection has been established, so the failure is in the transfer itself, not in reaching the host.","triggerScenarios":"A file provisioner block whose source is a directory; the SSH/WinRM connection succeeded but UploadDir returned an error mid-transfer.","commonSituations":"Destination path not writable or no space on the remote; SSH session dropped mid-transfer; WinRM upload size limits exceeded; permission/ownership mismatch on the target directory.","solutions":["Verify the destination directory exists and is writable by the connection user.","Free disk space on the remote host and retry the apply.","Increase connection timeouts / use bastion tuning if the session drops mid-upload.","For WinRM, raise the max request size or switch to SSH where possible."],"exampleFix":"// before\nconnection { host = aws_instance.web.public_ip }\nprovisioner \"file\" { source = \"./build\" destination = \"/opt/app\" } // Upload failed\n\n// after: ensure dest exists and is writable, widen timeout\nprovisioner \"remote-exec\" { inline = [\"mkdir -p /opt/app\"] }\nprovisioner \"file\" { source = \"./build\" destination = \"/opt/app\" }","handlingStrategy":"retry","validationCode":"// Pre-check the destination is writable by running a quick command first.\nfunc ensureWritableDir(comm communicator.Communicator, dst string) error {\n    cmd := &remote.Cmd{Command: fmt.Sprintf(\"mkdir -p %s && test -w %s\", filepath.Dir(dst), filepath.Dir(dst))}\n    return comm.Start(cmd)\n}","typeGuard":null,"tryCatchPattern":"// Retry the file provisioner's directory upload on transient errors.\nvar lastErr error\nfor i := 0; i < 3; i++ {\n    if err := copyFiles(ctx, comm, src, dst); err == nil {\n        return nil\n    } else if !isTransientCommError(err) {\n        return err // non-retryable\n    } else {\n        lastErr = err\n        time.Sleep(backoff(i))\n    }\n}\nreturn fmt.Errorf(\"Upload failed after retries: %w\", lastErr)","preventionTips":["Pre-create the destination directory on the remote with remote-exec before the file provisioner.","Ensure the connection user owns the destination path.","Add retries/timeouts in the connection block for flaky networks."],"tags":["terraform","file-provisioner","ssh","upload","transfer"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T20:17:04.800Z"}