{"record":{"id":"aca67183af136326","repo":"benbjohnson/litestream","slug":"webdav-cannot-delete-path-q-w","errorCode":null,"errorMessage":"webdav: cannot delete path %q: %w","messagePattern":"webdav: cannot delete path %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"webdav/replica_client.go","lineNumber":128,"sourceCode":"\n\tc.client.SetTimeout(c.Timeout)\n\n\tif err := c.client.Connect(); err != nil {\n\t\tc.client = nil\n\t\treturn nil, fmt.Errorf(\"webdav: cannot connect to server: %w\", err)\n\t}\n\n\treturn c.client, nil\n}\n\nfunc (c *ReplicaClient) DeleteAll(ctx context.Context) error {\n\tclient, err := c.init(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := client.RemoveAll(c.Path); err != nil && !os.IsNotExist(err) && !gowebdav.IsErrNotFound(err) {\n\t\treturn fmt.Errorf(\"webdav: cannot delete path %q: %w\", c.Path, err)\n\t}\n\n\tinternal.OperationTotalCounterVec.WithLabelValues(ReplicaClientType, \"DELETE\").Inc()\n\n\treturn nil\n}\n\nfunc (c *ReplicaClient) LTXFiles(ctx context.Context, level int, seek ltx.TXID, _ bool) (_ ltx.FileIterator, err error) {\n\tclient, err := c.init(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdir := litestream.LTXLevelDir(c.Path, level)\n\tfiles, err := client.ReadDir(dir)\n\tif err != nil {\n\t\tif os.IsNotExist(err) || gowebdav.IsErrNotFound(err) {\n\t\t\treturn ltx.NewFileInfoSliceIterator(nil), nil","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/webdav/replica_client.go#L110-L146","documentation":"DeleteAll removes the replica's entire path tree on the WebDAV server via client.RemoveAll(c.Path). If the removal fails for any reason other than 'path does not exist' (os.IsNotExist or gowebdav.IsErrNotFound), the error is wrapped with this message. It means the server refused or failed the recursive delete — typically permissions, a lock, or a transient server error.","triggerScenarios":"Calling DeleteAll (directly or via 'litestream replicate' teardown / replica reset paths) when the WebDAV account lacks write/delete permission on the path, the server returns 403/500/507, or a file is locked by another client.","commonSituations":"WebDAV user without delete rights on the collection; read-only mount on the server; another backup client holding a lock; quota/server-side errors during large recursive deletes; partial deletes leaving the collection in a locked state.","solutions":["Check that the configured WebDAV user has DELETE/PUT permission on the path (try deleting a test file with curl -X DELETE)","Inspect the wrapped error for the HTTP status: 403 = permissions, 507 = quota, 423 = locked","Verify nothing else (another Litestream instance or sync client) is holding locks on the tree","Retry the operation if the server error was transient; partial deletions are safe to re-run since not-found is tolerated","As a last resort delete the collection server-side (admin panel/SSH) and re-run"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// probe delete permission with a throwaway object first\nprobe := c.Path + \"/.litestream-permcheck\"\nif err := wc.Write(probe, strings.NewReader(\"\"), nil); err != nil {\n    return fmt.Errorf(\"no write/delete permission on %s: %w\", c.Path, err)\n}\nwc.Remove(probe)","typeGuard":null,"tryCatchPattern":"err := rc.DeleteAll(ctx)\nif err != nil && strings.Contains(err.Error(), \"cannot delete path\") {\n    var sd *gowebdav.StatusError\n    if errors.As(err, &sd) && sd.Status == http.StatusForbidden {\n        // escalate permissions or clean up server-side\n    }\n}","preventionTips":["Grant the WebDAV user DELETE rights on the replica collection","Avoid concurrent clients (other backup tools) locking the same tree","Monitor server quota (507) before large deletions","Treat not-found as success in your own wrappers; only handle genuine server errors"],"tags":["webdav","delete","permissions","http"],"backgroundTag":"http-error-response","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}