hashicorp/terraform · error
Upload failed: %v
Error message
Upload failed: %v
What it means
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.
Source
Thrown at internal/builtin/provisioners/file/resource_provisioner.go:188
return err
}
// disconnect when the context is canceled, which will close this after
// Apply as well.
go func() {
<-ctx.Done()
comm.Disconnect()
}()
info, err := os.Stat(src)
if err != nil {
return err
}
// If we're uploading a directory, short circuit and do that
if info.IsDir() {
if err := comm.UploadDir(dst, src); err != nil {
return fmt.Errorf("Upload failed: %v", err)
}
return nil
}
// We're uploading a file...
f, err := os.Open(src)
if err != nil {
return err
}
defer f.Close()
err = comm.Upload(dst, f)
if err != nil {
return fmt.Errorf("Upload failed: %v", err)
}
return err
}View on GitHub (pinned to c9def3e214)
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.
Example fix
// before
connection { host = aws_instance.web.public_ip }
provisioner "file" { source = "./build" destination = "/opt/app" } // Upload failed
// after: ensure dest exists and is writable, widen timeout
provisioner "remote-exec" { inline = ["mkdir -p /opt/app"] }
provisioner "file" { source = "./build" destination = "/opt/app" } Defensive patterns
Strategy: retry
Validate before calling
// Pre-check the destination is writable by running a quick command first.
func ensureWritableDir(comm communicator.Communicator, dst string) error {
cmd := &remote.Cmd{Command: fmt.Sprintf("mkdir -p %s && test -w %s", filepath.Dir(dst), filepath.Dir(dst))}
return comm.Start(cmd)
} Try / catch
// Retry the file provisioner's directory upload on transient errors.
var lastErr error
for i := 0; i < 3; i++ {
if err := copyFiles(ctx, comm, src, dst); err == nil {
return nil
} else if !isTransientCommError(err) {
return err // non-retryable
} else {
lastErr = err
time.Sleep(backoff(i))
}
}
return fmt.Errorf("Upload failed after retries: %w", lastErr) Prevention
- 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.
When it happens
Trigger: A file provisioner block whose source is a directory; the SSH/WinRM connection succeeded but UploadDir returned an error mid-transfer.
Common situations: 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.
Related errors
- Failed to upload script: %v
- Error starting script: %v
- connection type '%s' not supported
- SSH authentication failed (%s@%s): %w
- Error reading script: %s
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/c2aa550abe28b2a4.
Report an issue: GitHub.