kopia/kopia · error
unable to write WebDAV key
Error message
unable to write WebDAV key
What it means
After generating the TLS keypair, New() writes the private key to a temp file via tlsutil.WritePrivateKeyToFile so rclone can serve HTTPS WebDAV. Failure writing that key file is wrapped as 'unable to write WebDAV key'.
Solutions
- Confirm the temporary directory (td from os.MkdirTemp) still exists and is writable
- Check free space on the filesystem holding the temp dir
- Exclude kopia temp paths from aggressive tmp-cleaners
- Re-run the connect; a fresh temp dir is created each time
Defensive patterns
Strategy: validation
Validate before calling
td, err := os.MkdirTemp("", "kopia-rclone-probe")
if err != nil { return err }
defer os.RemoveAll(td)
probe := filepath.Join(td, "probe")
if err := os.WriteFile(probe, []byte("x"), 0o600); err != nil {
return fmt.Errorf("temp dir not writable: %w", err)
} Try / catch
_, err := rclone.New(ctx, opt, isCreate)
if err != nil && strings.Contains(err.Error(), "unable to write WebDAV key") {
log.Printf("failed writing TLS key to temp dir: %v; check TMPDIR permissions/space", err)
} Prevention
- Exclude kopia temp dirs from tmp-cleaner jobs
- Keep free space headroom on the temp filesystem
- Check SELinux/AppArmor policies for temp write access
When it happens
Trigger: tlsutil.WritePrivateKeyToFile(temporaryKeyPath, key) fails — temp dir deleted mid-run, permissions problem, or disk full.
Common situations: Temp cleaner daemon removing the kopia-rclone dir concurrently; full disk on /tmp; security software blocking key material written to disk.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- error creating file
- error writing script for execution
- unable to write cache directory marker
- unable to write htpasswd file
- unable to write to cache
AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07).
Data as JSON: /api/errors/4eb3c10efcd5eaee.
Report an issue: GitHub.
Appendix: source
Thrown at repo/blob/rclone/rclone_storage.go:290
// password file for rclone webdav server.
temporaryHtpassword := filepath.Join(td, "htpasswd")
defer func() {
// if we return this function without setting Storage, make sure to clean everything up.
if r.Storage == nil {
r.Close(ctx) //nolint:errcheck
}
}()
// write TLS files.
//nolint:mnd
cert, key, err := tlsutil.GenerateServerCertificate(ctx, 2048, 365*24*time.Hour, []string{"127.0.0.1"})
if err != nil {
return nil, errors.Wrap(err, "unable to generate server certificate")
}
if err = tlsutil.WritePrivateKeyToFile(temporaryKeyPath, key); err != nil {
return nil, errors.Wrap(err, "unable to write WebDAV key")
}
if err = tlsutil.WriteCertificateToFile(temporaryCertPath, cert); err != nil {
return nil, errors.Wrap(err, "unable to write WebDAV cert")
}
// temporary username and password to be used when communicating with rclone
webdavUsername := "u" + uuid.New().String()
webdavPassword := "p" + uuid.New().String()
if err = htpasswd.SetPassword(temporaryHtpassword, webdavUsername, webdavPassword, htpasswd.HashAPR1); err != nil {
return nil, errors.Wrap(err, "unable to write htpasswd file")
}
rcloneExe := defaultRCloneExe
if opt.RCloneExe != "" {
rcloneExe = opt.RCloneExe
}View on GitHub (pinned to 82495e54b5)