stalwartlabs/stalwart · critical

Migration aborted: {message}

Error message

Migration aborted: {message}

What it means

The migration routine's `abort` helper deliberately stops a migration with a human-readable reason, printing to stderr and panicking. It is used whenever preconditions for a safe migration are not met, ensuring the migration stops before modifying data.

Source

Thrown at crates/migration/src/lib.rs:95

        ValueClass::Any(AnyClass {
            subspace: SUBSPACE_PROPERTY,
            key: vec![0u8],
        }),
        DATABASE_SCHEMA_VERSION.serialize(),
    );

    server
        .store()
        .write(batch.build_all())
        .await
        .caused_by(trc::location!())?;

    Ok(())
}

fn abort(message: &str) -> ! {
    eprintln!("Migration aborted: {message}");
    panic!("Migration aborted: {message}");
}

async fn is_new_install(server: &Server) -> trc::Result<bool> {
    for subspace in [
        SUBSPACE_QUEUE_MESSAGE,
        SUBSPACE_REPORT_IN,
        SUBSPACE_REPORT_OUT,
        SUBSPACE_PROPERTY,
    ] {
        let mut has_data = false;

        server
            .store()
            .iterate(
                IterateParams::new(
                    AnyKey {
                        subspace,
                        key: vec![0u8],

View on GitHub (pinned to e962003857)

Solutions

  1. Read the {message} printed to stderr — it names the exact failed precondition.
  2. Complete the manual step referenced in the UPGRADING documentation for your version.
  3. Restore a backup and re-run migrations in the prescribed order.
  4. File an issue with the message if the precondition appears satisfied.
Defensive patterns

Strategy: try-catch

Validate before calling

// run migrations only after verifying preconditions
if !preconditions_met(&server).await { eprintln!("fix migration preconditions first"); std::process::exit(1); }

Try / catch

// catch the panic from abort in a wrapper
let result = std::panic::catch_unwind(|| run_migration_blocking());
if result.is_err() { eprintln!("migration aborted, restore backup"); }

Prevention

When it happens

Trigger: Any precondition check inside the migration flow (invoked via try_migrate) calls `abort(reason)` — e.g. the database is in a state the migration cannot handle, or a required earlier migration step was skipped.

Common situations: Migrating a partially-upgraded database; running migrations out of order; a manual intervention step (documented in UPGRADING) was not completed before running the migrator.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of stalwartlabs/stalwart@e962003857 (2026-09-06). Data as JSON: /api/errors/a5f39cc200c1c8b4. Report an issue: GitHub.