benbjohnson/litestream · error
webdav: cannot delete ltx file %q: %w
Error message
webdav: cannot delete ltx file %q: %w
What it means
This error wraps an underlying failure returned by the WebDAV server's Remove() call when Litestream tries to delete an LTX (replication) file. It is only raised when the error is neither os.IsNotExist nor a gowebdav IsErrNotFound, i.e. a real failure rather than the file already being gone. Litestream surfaces the offending filename and the wrapped cause so the replication cleanup can be diagnosed.
Source
Thrown at webdav/replica_client.go:365
}
return nil, fmt.Errorf("webdav: cannot read file %q: %w", filename, err)
}
return rc, nil
}
func (c *ReplicaClient) DeleteLTXFiles(ctx context.Context, a []*ltx.FileInfo) error {
client, err := c.init(ctx)
if err != nil {
return err
}
for _, info := range a {
filename := litestream.LTXFilePath(c.Path, info.Level, info.MinTXID, info.MaxTXID)
c.logger.Debug("deleting ltx file", "level", info.Level, "minTXID", info.MinTXID, "maxTXID", info.MaxTXID, "path", filename)
if err := client.Remove(filename); err != nil && !os.IsNotExist(err) && !gowebdav.IsErrNotFound(err) {
return fmt.Errorf("webdav: cannot delete ltx file %q: %w", filename, err)
}
internal.OperationTotalCounterVec.WithLabelValues(ReplicaClientType, "DELETE").Inc()
}
return nil
}
View on GitHub (pinned to 4ed7a308f6)
Solutions
- Check WebDAV credentials and that the account has DELETE permission on the replica path
- Read the wrapped cause (%w) in logs to identify the HTTP status from gowebdav and fix the server-side condition
- Verify the litestream.yml webdav url/path is correct and reachable (test with curl -X DELETE)
- Retry after transient network/server errors; Litestream will retry the sync loop and re-attempt deletion
- If files were already removed out-of-band, no action needed: not-found errors are tolerated
Example fix
// before: read-only WebDAV credentials cause 403 collector: litestream.yml webdav: url: https://dav.example.com/litestream username: reader password: **** // after: use credentials with write access url: https://dav.example.com/litestream username: writer password: ****
Defensive patterns
Strategy: try-catch
Validate before calling
// Go: check WebDAV reachability and permissions before deleting
client := gowebdav.NewClient(url)
client.SetBasicAuth(user, pass)
if err := client.Connect(); err != nil {
return fmt.Errorf("webdav unreachable: %w", err)
}
if _, err := client.ReadDir(basePath); err != nil {
return fmt.Errorf("no read/write access to %s: %w", basePath, err)
} Type guard
func isNotFoundErr(err error) bool {
return os.IsNotExist(err) || gowebdav.IsErrNotFound(err)
}
// treat only non-not-found errors as fatal, like litestream does Try / catch
if err := replicaClient.DeleteLTXFiles(ctx, infos); err != nil {
var davErr *gowebdav.StatusError
if errors.As(err, &davErr) {
log.Printf("webdav delete failed status=%d: %v", davErr.Status, davErr)
} else {
log.Printf("webdav delete failed: %v", err)
}
// transient: let the next sync retry
return err
} Prevention
- Grant the WebDAV service account DELETE permission on the replica directory
- Test the URL/credentials with curl -u user:pass -X DELETE before configuring
- Rotate credentials in litestream.yml in sync with the server
- Monitor logs for the wrapped cause (%w) to distinguish 401/403/5xx/network
When it happens
Trigger: Calling ReplicaClient.DeleteLTXFiles on a WebDAV replica when the server returns 403 Forbidden (read-only share/credentials), 401 Unauthorized (bad password), 500 (server-side error), a connection failure/time-out mid-delete, or a path escaping issues (bad c.Path base URL).
Common situations: WebDAV account lacks write permission on the replica directory; server returned 401 due to rotated credentials not updated in config; reverse proxy or gateway returned 5xx; transient network drop during retention cleanup; misconfigured path in litestream.yml.
Related errors
- remove ltx files: %w
- abs: cannot delete ltx file %q: %w
- abs: cannot list blobs: %w
- abs: cannot delete blob %q: %w
- close iterator: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/5efb233e7c3218c5.
Report an issue: GitHub.