hcengineering/platform · critical · Error

${infoFile} should present to restore

Error message

${infoFile} should present to restore

What it means

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.

Source

Thrown at server/backup/src/restore.ts:78

  storage: BackupStorage,
  accountDb: AccountDB | undefined,
  opt: {
    date: number
    merge?: boolean
    parallel?: number
    recheck?: boolean
    include?: Set<string>
    skip?: Set<string>
    progress?: (progress: number) => Promise<void>
    cleanIndexState?: boolean
    historyFile?: string
  }
): Promise<boolean> {
  const infoFile = 'backup.json.gz'
  const workspaceId = wsIds.uuid
  if (!(await storage.exists(infoFile))) {
    ctx.error('file not pressent', { file: infoFile })
    throw new Error(`${infoFile} should present to restore`)
  }
  const backupInfo: BackupInfo = JSON.parse(gunzipSync(new Uint8Array(await storage.loadFile(infoFile))).toString())
  let snapshots = backupInfo.snapshots
  if (opt.date !== -1) {
    const bk = backupInfo.snapshots.findIndex((it) => it.date === opt.date)
    if (bk === -1) {
      ctx.error('could not restore to', { date: opt.date, file: infoFile, workspaceId })
      throw new Error(`${infoFile} could not restore to ${opt.date}. Snapshot is missing.`)
    }
    snapshots = backupInfo.snapshots.slice(0, bk + 1)
  } else {
    opt.date = snapshots[snapshots.length - 1].date
  }

  if (backupInfo.domainHashes === undefined) {
    backupInfo.domainHashes = {}
  }
  ctx.info('restore to ', { id: opt.date, date: new Date(opt.date).toDateString() })

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Ensure backup.json.gz exists in the target storage (re-run backup if missing).
  2. Verify the storage endpoint/bucket/prefix passed to restore matches the backup location.
  3. Check IAM/storage credentials allow listing and reading the object (exists() can fail on permissions).
  4. Confirm bucket lifecycle rules are not deleting the manifest.

Example fix

// restore invocation
// before
restore(ctx, storageOf('wrong-prefix'), wsIds)
// after
restore(ctx, storageOf('backups/ws-uuid'), wsIds) // contains backup.json.gz
Defensive patterns

Strategy: validation

Validate before calling

// gate restore on manifest presence
if (!(await storage.exists('backup.json.gz'))) {
  throw new Error('backup.json.gz missing in target storage; restore aborted')
}

Try / catch

try {
  await restore(ctx, storage, wsIds, opt)
} catch (err) {
  if (err instanceof Error && err.message.includes('should present to restore')) {
    // abort restore workflow, alert operators, verify storage path
  } else throw err
}

Prevention

When it happens

Trigger: Invoking restore (restore, restoreFromv6All, restoreTrustedV6Workspace, devTool, drawLine/drawLineCommand) against a BackupStorage whose root has no backup.json.gz.

Common situations: 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.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/8ee34b2e704ee2dd. Report an issue: GitHub.