{"record":{"id":"2563f6168b9897d9","repo":"benbjohnson/litestream","slug":"webdav-cannot-read-directory-q-w","errorCode":null,"errorMessage":"webdav: cannot read directory %q: %w","messagePattern":"webdav: cannot read directory %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"webdav/replica_client.go","lineNumber":148,"sourceCode":"\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\n\t\t}\n\t\treturn nil, fmt.Errorf(\"webdav: cannot read directory %q: %w\", dir, err)\n\t}\n\n\tinfos := make([]*ltx.FileInfo, 0, len(files))\n\tfor _, fi := range files {\n\t\tif fi.IsDir() {\n\t\t\tcontinue\n\t\t}\n\n\t\tminTXID, maxTXID, err := ltx.ParseFilename(path.Base(fi.Name()))\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t} else if minTXID < seek {\n\t\t\tcontinue\n\t\t}\n\n\t\tinfos = append(infos, &ltx.FileInfo{\n\t\t\tLevel:     level,\n\t\t\tMinTXID:   minTXID,","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/webdav/replica_client.go#L130-L166","documentation":"LTXFiles lists the LTX files for a compaction level by reading the directory <path>/<level> on the WebDAV server. Missing directories are treated as an empty file list (no error), but any other ReadDir failure (permissions, server error, timeout) is wrapped with this message.","triggerScenarios":"Listing replicas ('litestream replicas' / restore path / retention scans) when the WebDAV server returns a non-404 error for PROPFIND on the level directory: 403, 500, connection drop, or timeout.","commonSituations":"WebDAV user lacking read permission on the directory; server outage mid-listing; transient network failure; server-side path permissions changed after the replica was created; directory exists but PROPFIND depth is restricted by the server.","solutions":["Verify the directory is listable: curl -u user:pass -X PROPFIND https://host/<path>/0 -H 'Depth: 1'","Check permissions on the LTX level directories for the configured WebDAV user","Look at the wrapped error for the root cause (status code, timeout, TLS) and fix accordingly","Retry on transient errors; note a 404 is already handled gracefully as an empty iterator","If the replica tree is broken, re-seed it with a fresh 'litestream replicate' run"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"dir := litestream.LTXLevelDir(path, level)\nreq, _ := http.NewRequest(http.MethodPropfind, baseURL+dir, nil)\nreq.SetBasicAuth(user, pass)\nresp, err := httpClient.Do(req)\nif err != nil { return err }\nresp.Body.Close()\nif resp.StatusCode != 207 && resp.StatusCode != 404 {\n    return fmt.Errorf(\"PROPFIND %s: %s\", dir, resp.Status)\n}","typeGuard":null,"tryCatchPattern":"it, err := rc.LTXFiles(ctx, level)\nif err != nil && strings.Contains(err.Error(), \"cannot read directory\") {\n    // fall back to empty listing and retry later, or surface the wrapped cause\n    return fmt.Errorf(\"listing level %d failed: %w\", level, err)\n}","preventionTips":["Ensure the WebDAV user can PROPFIND (read) the replica directories","Expect level directories to be absent pre-first-replication — 404 is already handled as empty","Retry on transient server/network errors; they surface wrapped here","Keep server-side permissions stable across the whole LTX level tree"],"tags":["webdav","directory","list","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"}