{"record":{"id":"20e3a68980db2d89","repo":"benbjohnson/litestream","slug":"webdav-cannot-create-parent-directory-q-w","errorCode":null,"errorMessage":"webdav: cannot create parent directory %q: %w","messagePattern":"webdav: cannot create parent directory %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"webdav/replica_client.go","lineNumber":278,"sourceCode":"\t}\n\tdefer func() {\n\t\t_ = tmpFile.Close()\n\t\t_ = os.Remove(tmpFile.Name())\n\t}()\n\n\tfullReader := io.MultiReader(&buf, rd)\n\n\tsize, err := io.Copy(tmpFile, fullReader)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"webdav: cannot copy to temp file: %w\", err)\n\t}\n\n\tif _, err := tmpFile.Seek(0, io.SeekStart); err != nil {\n\t\treturn nil, fmt.Errorf(\"webdav: cannot seek temp file: %w\", err)\n\t}\n\n\tif err := client.MkdirAll(path.Dir(filename), 0755); err != nil {\n\t\treturn nil, fmt.Errorf(\"webdav: cannot create parent directory %q: %w\", path.Dir(filename), err)\n\t}\n\n\t// Upload with Content-Length header using seekable temp file.\n\t// WriteStreamWithLength requires both a seekable reader and known size,\n\t// which we now have from the temp file. This avoids chunked encoding\n\t// and ensures reliable uploads across all WebDAV server configurations.\n\tif err := client.WriteStreamWithLength(filename, tmpFile, size, 0644); err != nil {\n\t\treturn nil, fmt.Errorf(\"webdav: cannot write file %q: %w\", filename, err)\n\t}\n\n\tinternal.OperationTotalCounterVec.WithLabelValues(ReplicaClientType, \"PUT\").Inc()\n\tinternal.OperationBytesCounterVec.WithLabelValues(ReplicaClientType, \"PUT\").Add(float64(size))\n\n\treturn &ltx.FileInfo{\n\t\tLevel:     level,\n\t\tMinTXID:   minTXID,\n\t\tMaxTXID:   maxTXID,\n\t\tSize:      size,","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/webdav/replica_client.go#L260-L296","documentation":"WriteLTXFile ensures the destination directory exists on the WebDAV server via client.MkdirAll before uploading. This error wraps that failure: the server rejected directory creation (permissions, locked collection, or HTTP-level problem).","triggerScenarios":"Uploading to a path whose parent cannot be created on the WebDAV server: insufficient WebDAV credentials, read-only collection, or the server rejecting MKCOL requests for the path prefix.","commonSituations":"WebDAV user lacking write rights to the target collection, misconfigured path in the litestream config (e.g. wrong base URL segment), servers that disallow MKCOL at certain depths, or an intermediate path segment existing as a FILE not a directory.","solutions":["Verify the WebDAV username/password has write permission on the target path","Check that no file exists at a path segment that must be a directory","Test manually: curl -X MKCOL against the parent path to see the server's response","Correct the configured replica path/URL in the litestream config"],"exampleFix":"// before litestream.yml\nurl: webdav://user:pass@dav.example.com/wrong-locked-path/db\n// after\nurl: webdav://user:pass@dav.example.com/litestream/db","handlingStrategy":"try-catch","validationCode":"client, _ := gowebdav.NewClient(serverURL, user, pass)\nclient.Connect() // fails early on auth problems\nif err := client.MkdirAll(basePath, 0755); err != nil { return fmt.Errorf(\"precheck mkdir failed: %w\", err) }","typeGuard":null,"tryCatchPattern":"if err := writeLTX(ctx); err != nil {\n    var pe *goserver.PathError\n    if strings.Contains(err.Error(), \"cannot create parent directory\") { verify credentials and that no file blocks the path segment }\n}","preventionTips":["Pre-create the replica base directory and grant write access","Test MKCOL permission with curl before configuring litestream","Ensure no file exists where a directory segment is required","Validate the configured replica path for typos"],"tags":["webdav","mkdir","permissions"],"backgroundTag":"mkdir-permission-denied","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"}