{"record":{"id":"ca66ff0205a98a2e","repo":"Kareadita/Kavita","slug":"bad-copy-files-for-download","errorCode":null,"errorMessage":"bad-copy-files-for-download","messagePattern":"bad-copy-files-for-download","errorType":"exception","errorClass":"KavitaException","httpStatus":null,"severity":"error","filePath":"Kavita.Services/ArchiveService.cs","lineNumber":283,"sourceCode":"    /// <returns>Path to the temp zip</returns>\n    /// <exception cref=\"KavitaException\"></exception>\n    public string CreateZipForDownload(IEnumerable<string> files, string tempFolder)\n    {\n        var dateString = DateTime.UtcNow.ToShortDateString().Replace(\"/\", \"_\");\n\n        var tempLocation = Path.Join(directoryService.TempDirectory, $\"{tempFolder}_{dateString}\");\n        var potentialExistingFile = directoryService.FileSystem.FileInfo.New(Path.Join(directoryService.TempDirectory, $\"kavita_{tempFolder}_{dateString}.zip\"));\n        if (potentialExistingFile.Exists)\n        {\n            // A previous download exists, just return it immediately\n            return potentialExistingFile.FullName;\n        }\n\n        directoryService.ExistOrCreate(tempLocation);\n\n        if (!directoryService.CopyFilesToDirectory(files, tempLocation))\n        {\n            throw new KavitaException(\"bad-copy-files-for-download\");\n        }\n\n        var zipPath = Path.Join(directoryService.TempDirectory, $\"kavita_{tempFolder}_{dateString}.zip\");\n        try\n        {\n            ZipFile.CreateFromDirectory(tempLocation, zipPath);\n            // Remove the folder as we have the zip\n            directoryService.ClearAndDeleteDirectory(tempLocation);\n        }\n        catch (AggregateException ex)\n        {\n            logger.LogError(ex, \"There was an issue creating temp archive\");\n            throw new KavitaException(\"generic-create-temp-archive\");\n        }\n\n        return zipPath;\n    }\n","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/Kareadita/Kavita/blob/9c3e5400007f8a0282f7d883f2ad5e71716e514d/Kavita.Services/ArchiveService.cs#L265-L301","documentation":"Thrown by ArchiveService.CreateZipForDownload (line 283) when directoryService.CopyFilesToDirectory(files, tempLocation) returns false, i.e. one or more of the requested source files could not be copied into the staging temp folder. The method builds a downloadable .zip from a flat file list (used by ServerController log download and DownloadController bookmark download). The temp folder is created just before, so failure is typically a missing/unreadable source file or a disk/permission problem.","triggerScenarios":"Requesting a download (server logs zip, or bookmarks zip) where at least one source path in 'files' does not exist, was deleted, is locked, or the temp directory is not writable. The controller surfaces this KavitaException as a 400.","commonSituations":"Log files rolled/removed between listing and copy; bookmark file path stale after a config move; temp directory on a read-only or full volume; a source file held open by another process on Windows.","solutions":["Verify every path in 'files' exists and is readable before calling CreateZipForDownload (filter out missing ones).","Confirm directoryService.TempDirectory is writable and the disk has free space.","On Windows, ensure no other process holds an exclusive lock on the source files."],"exampleFix":"// before\nif (!directoryService.CopyFilesToDirectory(files, tempLocation))\n    throw new KavitaException(\"bad-copy-files-for-download\");\n\n// caller — prefilter missing files\nvar existing = files.Where(f => directoryService.FileSystem.File.Exists(f)).ToList();\nvar zipPath = archiveService.CreateZipForDownload(existing, tempFolder);","handlingStrategy":"validation","validationCode":"// Filter to existing, readable files before zipping for download\nvar files = requestedFiles\n    .Where(f => directoryService.FileSystem.File.Exists(f))\n    .ToList();\nif (files.Count == 0) return BadRequest(\"No files available for download\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Resolve file paths from a fresh source right before download (logs/bookmarks can roll/change).","Ensure the Temp directory is writable with free space.","On Windows, ensure source files are not exclusively locked by another process."],"tags":["archive","download","filesystem","io-error"],"backgroundTag":null,"analyzedSha":"9c3e5400007f8a0282f7d883f2ad5e71716e514d","analyzedAt":"2026-08-13T19:06:05.897Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}