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
- Read the {message} printed to stderr — it names the exact failed precondition.
- Complete the manual step referenced in the UPGRADING documentation for your version.
- Restore a backup and re-run migrations in the prescribed order.
- 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
- Read stderr output of the migrator — abort always prints the reason.
- Follow UPGRADING.md manual steps in order for every release.
- Run migrations in a staging copy of the database first.
- Keep backups so an aborted migration can be rolled back cleanly.
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
- Unknown database schema version, expected {} or below, found
- Failed to scan keys
- Failed to delete keys
- unwrap_tls called on non-TLS acceptor
- Failed to parse calendar template
AI-assisted analysis of stalwartlabs/stalwart@e962003857 (2026-09-06).
Data as JSON: /api/errors/a5f39cc200c1c8b4.
Report an issue: GitHub.