Stirling-Tools/Stirling-PDF · error · Error

No valid files found in storage for ZIP download

Error message

No valid files found in storage for ZIP download

What it means

Thrown by downloadFilesAsZip when, after iterating all requested files and looking each up in IndexedDB, zero files were successfully retrieved. Unlike error 70 (single file), this aggregates across the whole batch and fires only when every single lookup failed, meaning there is nothing to put in the ZIP. The function fails fast rather than creating an empty archive.

Source

Thrown at frontend/editor/src/core/utils/downloadUtils.ts:78

): Promise<void> {
  if (files.length === 0) {
    throw new Error("No files provided for ZIP download");
  }

  // Convert stored files to File objects (tracking ids so export policies can
  // version the in-editor file).
  const filesToZip: File[] = [];
  const fileIds: (string | undefined)[] = [];
  for (const fileWithUrl of files) {
    const stirlingFile = await fileStorage.getStirlingFile(fileWithUrl.id);
    if (stirlingFile) {
      filesToZip.push(stirlingFile);
      fileIds.push(fileWithUrl.id);
    }
  }

  if (filesToZip.length === 0) {
    throw new Error("No valid files found in storage for ZIP download");
  }

  // Enforce any export-triggered policy on each PDF before they're zipped.
  const enforced = await enforceExportPolicies(filesToZip, fileIds);

  // Generate default filename if not provided
  const finalZipFilename =
    zipFilename ||
    `files-${new Date().toISOString().slice(0, 19).replace(/[:-]/g, "")}.zip`;

  // Create and download ZIP
  const { zipFile } = await zipFileService.createZipFromFiles(
    enforced,
    finalZipFilename,
  );
  await downloadFile({ data: zipFile, filename: finalZipFilename });
}

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Check each file's presence in storage before enabling the ZIP download button; disable it if none survive.
  2. Re-run the operations or re-upload the source files to repopulate storage.
  3. Surface a user-facing message listing which files are missing rather than a generic error.
  4. Increase storage retention limits if the entire set is being evicted.

Example fix

// before
await downloadFilesAsZip(files); // throws if all evicted
// after
const available = [];
for (const f of files) { if (await fileStorage.getStirlingFile(f.id)) available.push(f); }
if (available.length === 0) { notify('No files are available to download.'); return; }
await downloadFilesAsZip(available);
Defensive patterns

Strategy: validation

Validate before calling

import { fileStorage } from '@app/services/fileStorage';

async function filterAvailableFiles(files: StirlingFileStub[]): Promise<StirlingFileStub[]> {
  const available: StirlingFileStub[] = [];
  for (const f of files) {
    if (await fileStorage.getStirlingFile(f.id)) available.push(f);
  }
  return available;
}

const available = await filterAvailableFiles(files);
if (available.length === 0) {
  showUser('None of the selected files are available in storage.');
  return;
}

Type guard

async function availableFileCount(files: StirlingFileStub[]): Promise<number> {
  let n = 0;
  for (const f of files) if (await fileStorage.getStirlingFile(f.id)) n++;
  return n;
}

Try / catch

try {
  await downloadFilesAsZip(files);
} catch (e) {
  if (e instanceof Error && e.message.includes('No valid files')) {
    showUser('No files are available to download. They may have been cleared from storage.');
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling downloadFilesAsZip(files) where every file.id returns null from fileStorage.getStirlingFile. This is the batch equivalent of error 70 occurring for 100% of the input.

Common situations: All files in the selection were evicted from the LRU cache or cleared from storage. The FileContext holds stale references to files that were never persisted or have since been removed. A bulk 'download all' action was triggered after a storage wipe.

Related errors


AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13). Data as JSON: /api/errors/2f62d8cebb900c59. Report an issue: GitHub.