strapi/strapi · error · Error

restore failed ${error}

Error message

restore failed ${error}

What it means

Thrown by beforeTransfer() as a catch-all wrapper around the restore preparation steps: #handleAssetsBackup(), #deleteAllAssets(trx), and #deleteFromRestoreOptions(). The original error is stringified into the message. It runs inside a transaction.attach() callback, so the transaction will be rolled back by the engine on failure. The inner error could be a file-system failure, a database error, or a missing-options error.

Source

Thrown at packages/core/data-transfer/src/strapi/providers/local-destination/index.ts:193

    this.options.onTransferPhase?.('Local: preparing destination for restore…');

    await this.transaction?.attach(async (trx) => {
      try {
        if (this.options.strategy === 'restore') {
          if (this.#areAssetsIncluded()) {
            this.options.onTransferPhase?.('Local: backing up existing upload folder…');
          }
          await this.#handleAssetsBackup();
          if (this.#areAssetsIncluded()) {
            this.options.onTransferPhase?.('Local: deleting existing media files from disk…');
          }
          await this.#deleteAllAssets(trx);
          this.options.onTransferPhase?.('Local: clearing database content for restore…');
          await this.#deleteFromRestoreOptions();
        }
      } catch (error) {
        throw new Error(`restore failed ${error}`);
      }
    });
  }

  getMetadata(): IMetadata {
    this.#reportInfo('getting metadata');
    assertValidStrapi(this.strapi, 'Not able to get Schemas');
    const strapiVersion = this.strapi.config.get<string>('info.strapi');
    const createdAt = new Date().toISOString();

    return {
      createdAt,
      strapi: {
        version: strapiVersion,
      },
    };
  }

View on GitHub (pinned to 4a4101264d)

Solutions

  1. Inspect the inner error (the part after 'restore failed ') to identify which sub-step failed.
  2. For filesystem errors, check write permissions on strapi.dirs.static.public and the uploads subdirectory.
  3. For database errors, check database connectivity, locks, and constraints.
  4. For upload-provider errors, verify the upload provider configuration and that referenced files exist.
  5. Re-run the transfer after fixing the root cause; the transaction rollback ensures the database is in a consistent pre-transfer state.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await provider.beforeTransfer();
} catch (e) {
  const msg = e instanceof Error ? e.message : String(e);
  if (msg.startsWith('restore failed ')) {
    const inner = msg.slice('restore failed '.length);
    console.error('Restore preparation failed. Root cause:', inner);
    // The transaction is rolled back; the DB is in its pre-transfer state.
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Any failure during the restore preparation phase: the uploads directory lacks write permissions (assets backup fails), a database query in deleteMany fails, the upload provider's delete() throws for a file, or #deleteFromRestoreOptions hits a missing restore option.

Common situations: Insufficient filesystem permissions on the public/uploads directory. A corrupt or locked database row during deleteMany. A custom upload provider whose delete() throws on missing files. Disk full during the backup move operation.

Related errors


AI-assisted analysis of strapi/strapi@4a4101264d (2026-08-12). Data as JSON: /api/errors/953317675971e60c. Report an issue: GitHub.