nocobase/nocobase · error

Backup file ${filterByTk} not found

Error message

Backup file ${filterByTk} not found

What it means

Thrown by the backup-files download action when the requested backup either does not resolve to a downloadable state or its name lacks the DUMPED_EXTENSION suffix. The action verifies via Dumper.getFileStatus that the target exists with status 'ok' before streaming it as an attachment; otherwise it reports the file as not found.

Source

Thrown at packages/plugins/@nocobase/plugin-backup-restore/src/server/resourcers/backup-files.ts:142

      await next();
    },

    /**
     * download backup file
     * @param ctx
     * @param next
     */
    async download(ctx, next) {
      const { filterByTk } = ctx.action.params;
      const dumper = new Dumper(ctx.app);

      const filePath = dumper.backUpFilePath(filterByTk);

      const fileState = await Dumper.getFileStatus(filePath);

      if (!filterByTk.endsWith(`.${DUMPED_EXTENSION}`) || fileState.status !== 'ok') {
        throw new Error(`Backup file ${filterByTk} not found`);
      }

      ctx.attachment(filePath);
      ctx.body = fs.createReadStream(filePath);
      await next();
    },

    async restore(ctx, next) {
      const { dataTypes, filterByTk, key } = ctx.action.params.values;

      const filePath = (() => {
        if (key) {
          const tmpDir = os.tmpdir();
          return path.resolve(tmpDir, key);
        }

        if (filterByTk) {
          const dumper = new Dumper(ctx.app);

View on GitHub (pinned to fa42722fef)

Solutions

  1. Refresh the backup-files list and confirm the file still exists on disk in the backup storage directory.
  2. Ensure filterByTk is the full file name including the DUMPED_EXTENSION (e.g. `backup-20260831.dump`).
  3. If status is stuck as in_progress, remove the stale .lock file for that backup and retry.
  4. Check that the app's backup storage path/volume points to the directory that actually contains the dump.
  5. Re-run a backup if the archive is gone.

Example fix

// before
await api.resource('backup-files').download({ filterByTk: 'backup-20260831' });
// after
const name = 'backup-20260831.dump'; // include extension, ensure exists
const list = await api.resource('backup-files').list({});
if (list.data.data.some((f) => f.name === name && f.status === 'ok')) {
  await api.resource('backup-files').download({ filterByTk: name });
}
Defensive patterns

Strategy: validation

Validate before calling

async function canDownload(name) {
  if (!name.endsWith('.dump')) return false;
  const { data } = await api.resource('backup-files').list({});
  const f = data.data.find((x) => x.name === name);
  return Boolean(f && f.status === 'ok');
}
// call before download

Type guard

function isDownloadable(f) {
  return f != null && f.status === 'ok' && typeof f.name === 'string' && f.name.endsWith('.dump');
}

Try / catch

try {
  await api.resource('backup-files').download({ filterByTk: name });
} catch (e) {
  if (new RegExp(`Backup file ${name} not found`).test(e.message)) {
    refreshBackupList(); // stale UI or deleted file
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: GET backup-files:download with filterByTk whose name doesn't end with the dumped extension (e.g. missing `.dump`), the file was deleted from storage, or getFileStatus returns status other than 'ok' (e.g. stale in_progress lock or unreadable path).

Common situations: UI list is stale and the row refers to a deleted file; backup storage volume was remounted/replaced; download link built from a name without extension; concurrent restore/cleanup removed the file between listing and download.

Related errors


AI-assisted analysis of nocobase/nocobase@fa42722fef (2026-09-01). Data as JSON: /api/errors/f79ebdd244125a87. Report an issue: GitHub.