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

  1. Verify the destination directory exists and is writable by the connection user.
  2. Free disk space on the remote host and retry the apply.
  3. Increase connection timeouts / use bastion tuning if the session drops mid-upload.
  4. 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

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


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