{"record":{"id":"8ee34b2e704ee2dd","repo":"hcengineering/platform","slug":"infofile-should-present-to-restore","errorCode":null,"errorMessage":"${infoFile} should present to restore","messagePattern":"(.+?) should present to restore","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"server/backup/src/restore.ts","lineNumber":78,"sourceCode":"  storage: BackupStorage,\n  accountDb: AccountDB | undefined,\n  opt: {\n    date: number\n    merge?: boolean\n    parallel?: number\n    recheck?: boolean\n    include?: Set<string>\n    skip?: Set<string>\n    progress?: (progress: number) => Promise<void>\n    cleanIndexState?: boolean\n    historyFile?: string\n  }\n): Promise<boolean> {\n  const infoFile = 'backup.json.gz'\n  const workspaceId = wsIds.uuid\n  if (!(await storage.exists(infoFile))) {\n    ctx.error('file not pressent', { file: infoFile })\n    throw new Error(`${infoFile} should present to restore`)\n  }\n  const backupInfo: BackupInfo = JSON.parse(gunzipSync(new Uint8Array(await storage.loadFile(infoFile))).toString())\n  let snapshots = backupInfo.snapshots\n  if (opt.date !== -1) {\n    const bk = backupInfo.snapshots.findIndex((it) => it.date === opt.date)\n    if (bk === -1) {\n      ctx.error('could not restore to', { date: opt.date, file: infoFile, workspaceId })\n      throw new Error(`${infoFile} could not restore to ${opt.date}. Snapshot is missing.`)\n    }\n    snapshots = backupInfo.snapshots.slice(0, bk + 1)\n  } else {\n    opt.date = snapshots[snapshots.length - 1].date\n  }\n\n  if (backupInfo.domainHashes === undefined) {\n    backupInfo.domainHashes = {}\n  }\n  ctx.info('restore to ', { id: opt.date, date: new Date(opt.date).toDateString() })","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/backup/src/restore.ts#L60-L96","documentation":"The restore flow requires the 'backup.json.gz' manifest in storage before restoring; if storage.exists(infoFile) is false it logs 'file not pressent' and throws this Error. restore() callers include restoreFromv6All, restoreTrustedV6Workspace and dev tooling.","triggerScenarios":"Invoking restore (restore, restoreFromv6All, restoreTrustedV6Workspace, devTool, drawLine/drawLineCommand) against a BackupStorage whose root has no backup.json.gz.","commonSituations":"Restore pointed at the wrong bucket/prefix; disaster-recovery drill against an empty region; manifest lost to bucket lifecycle rules; restore run before the backup job finished.","solutions":["Ensure backup.json.gz exists in the target storage (re-run backup if missing).","Verify the storage endpoint/bucket/prefix passed to restore matches the backup location.","Check IAM/storage credentials allow listing and reading the object (exists() can fail on permissions).","Confirm bucket lifecycle rules are not deleting the manifest."],"exampleFix":"// restore invocation\n// before\nrestore(ctx, storageOf('wrong-prefix'), wsIds)\n// after\nrestore(ctx, storageOf('backups/ws-uuid'), wsIds) // contains backup.json.gz","handlingStrategy":"validation","validationCode":"// gate restore on manifest presence\nif (!(await storage.exists('backup.json.gz'))) {\n  throw new Error('backup.json.gz missing in target storage; restore aborted')\n}","typeGuard":null,"tryCatchPattern":"try {\n  await restore(ctx, storage, wsIds, opt)\n} catch (err) {\n  if (err instanceof Error && err.message.includes('should present to restore')) {\n    // abort restore workflow, alert operators, verify storage path\n  } else throw err\n}","preventionTips":["Verify backup completion before scheduling restores.","Store the storage location used by the backup alongside workspace metadata and reuse it for restore.","Run disaster-recovery drills with the same storage config as production.","Protect backup.json.gz from lifecycle deletion and restrict write/delete IAM on the backup bucket."],"tags":["backup","restore","missing-file","storage"],"backgroundTag":"backup-manifest-missing","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}