{"record":{"id":"f79ebdd244125a87","repo":"nocobase/nocobase","slug":"backup-file-filterbytk-not-found","errorCode":null,"errorMessage":"Backup file ${filterByTk} not found","messagePattern":"Backup file (.+?) not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/plugins/@nocobase/plugin-backup-restore/src/server/resourcers/backup-files.ts","lineNumber":142,"sourceCode":"\n      await next();\n    },\n\n    /**\n     * download backup file\n     * @param ctx\n     * @param next\n     */\n    async download(ctx, next) {\n      const { filterByTk } = ctx.action.params;\n      const dumper = new Dumper(ctx.app);\n\n      const filePath = dumper.backUpFilePath(filterByTk);\n\n      const fileState = await Dumper.getFileStatus(filePath);\n\n      if (!filterByTk.endsWith(`.${DUMPED_EXTENSION}`) || fileState.status !== 'ok') {\n        throw new Error(`Backup file ${filterByTk} not found`);\n      }\n\n      ctx.attachment(filePath);\n      ctx.body = fs.createReadStream(filePath);\n      await next();\n    },\n\n    async restore(ctx, next) {\n      const { dataTypes, filterByTk, key } = ctx.action.params.values;\n\n      const filePath = (() => {\n        if (key) {\n          const tmpDir = os.tmpdir();\n          return path.resolve(tmpDir, key);\n        }\n\n        if (filterByTk) {\n          const dumper = new Dumper(ctx.app);","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/nocobase/nocobase/blob/fa42722fefe44265490dff2c27d79e2882bce4fa/packages/plugins/@nocobase/plugin-backup-restore/src/server/resourcers/backup-files.ts#L124-L160","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Refresh the backup-files list and confirm the file still exists on disk in the backup storage directory.","Ensure filterByTk is the full file name including the DUMPED_EXTENSION (e.g. `backup-20260831.dump`).","If status is stuck as in_progress, remove the stale .lock file for that backup and retry.","Check that the app's backup storage path/volume points to the directory that actually contains the dump.","Re-run a backup if the archive is gone."],"exampleFix":"// before\nawait api.resource('backup-files').download({ filterByTk: 'backup-20260831' });\n// after\nconst name = 'backup-20260831.dump'; // include extension, ensure exists\nconst list = await api.resource('backup-files').list({});\nif (list.data.data.some((f) => f.name === name && f.status === 'ok')) {\n  await api.resource('backup-files').download({ filterByTk: name });\n}","handlingStrategy":"validation","validationCode":"async function canDownload(name) {\n  if (!name.endsWith('.dump')) return false;\n  const { data } = await api.resource('backup-files').list({});\n  const f = data.data.find((x) => x.name === name);\n  return Boolean(f && f.status === 'ok');\n}\n// call before download","typeGuard":"function isDownloadable(f) {\n  return f != null && f.status === 'ok' && typeof f.name === 'string' && f.name.endsWith('.dump');\n}","tryCatchPattern":"try {\n  await api.resource('backup-files').download({ filterByTk: name });\n} catch (e) {\n  if (new RegExp(`Backup file ${name} not found`).test(e.message)) {\n    refreshBackupList(); // stale UI or deleted file\n    return;\n  }\n  throw e;\n}","preventionTips":["Always pass the full file name including the .dump extension as filterByTk","Refresh the backup list before offering download links","Verify backup storage path/volume after server or container changes","Check the file exists on disk before sharing download URLs"],"tags":["backup","filesystem","download","not-found"],"backgroundTag":"backup-file-not-found","analyzedSha":"fa42722fefe44265490dff2c27d79e2882bce4fa","analyzedAt":"2026-09-01T00:54:31.202Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}