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

  1. Verify every path in 'files' exists and is readable before calling CreateZipForDownload (filter out missing ones).
  2. Confirm directoryService.TempDirectory is writable and the disk has free space.
  3. 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

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


AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13). Data as JSON: /api/errors/ca66ff0205a98a2e. Report an issue: GitHub.