Kareadita/Kavita · error · KavitaException
bad-copy-files-for-download
Error message
bad-copy-files-for-download
What it means
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.
Source
Thrown at Kavita.Services/ArchiveService.cs:283
/// <returns>Path to the temp zip</returns>
/// <exception cref="KavitaException"></exception>
public string CreateZipForDownload(IEnumerable<string> files, string tempFolder)
{
var dateString = DateTime.UtcNow.ToShortDateString().Replace("/", "_");
var tempLocation = Path.Join(directoryService.TempDirectory, $"{tempFolder}_{dateString}");
var potentialExistingFile = directoryService.FileSystem.FileInfo.New(Path.Join(directoryService.TempDirectory, $"kavita_{tempFolder}_{dateString}.zip"));
if (potentialExistingFile.Exists)
{
// A previous download exists, just return it immediately
return potentialExistingFile.FullName;
}
directoryService.ExistOrCreate(tempLocation);
if (!directoryService.CopyFilesToDirectory(files, tempLocation))
{
throw new KavitaException("bad-copy-files-for-download");
}
var zipPath = Path.Join(directoryService.TempDirectory, $"kavita_{tempFolder}_{dateString}.zip");
try
{
ZipFile.CreateFromDirectory(tempLocation, zipPath);
// Remove the folder as we have the zip
directoryService.ClearAndDeleteDirectory(tempLocation);
}
catch (AggregateException ex)
{
logger.LogError(ex, "There was an issue creating temp archive");
throw new KavitaException("generic-create-temp-archive");
}
return zipPath;
}
View on GitHub (pinned to 9c3e540000)
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.
Example fix
// before
if (!directoryService.CopyFilesToDirectory(files, tempLocation))
throw new KavitaException("bad-copy-files-for-download");
// caller — prefilter missing files
var existing = files.Where(f => directoryService.FileSystem.File.Exists(f)).ToList();
var zipPath = archiveService.CreateZipForDownload(existing, tempFolder); Defensive patterns
Strategy: validation
Validate before calling
// Filter to existing, readable files before zipping for download
var files = requestedFiles
.Where(f => directoryService.FileSystem.File.Exists(f))
.ToList();
if (files.Count == 0) return BadRequest("No files available for download"); Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- generic-create-temp-archive
- {archivePath} does not exist on disk
- There was an error when extracting {archivePath}. Check the
- Failed to create database backup at {backupPath}
- file-doesnt-exist
AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13).
Data as JSON: /api/errors/ca66ff0205a98a2e.
Report an issue: GitHub.