nautechsystems/nautilus_trader · critical · anyhow::Error
Execution payload protection version {version} is newer than
Error message
Execution payload protection version {version} is newer than supported version {EXECUTION_PAYLOAD_PROTOCOL_VERSION} What it means
A guard in `ensure_execution_payload_storage`: the database already has an execution payload protection marker whose protocol version differs from the version this binary supports (EXECUTION_PAYLOAD_PROTOCOL_VERSION). Because the stored version is newer than (or simply not equal to) what this build understands, the node refuses to proceed rather than corrupting protected signed-transaction storage.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:4617
.await
.map_err(|e| anyhow::anyhow!("Failed to activate verification schema: {e}"))?;
transaction
.commit()
.await
.map_err(|e| anyhow::anyhow!("Failed to commit verification migration: {e}"))?;
Ok(())
}
/// Activates or resumes protected signed-transaction storage for this database.
pub(crate) async fn ensure_execution_payload_storage(
&self,
keys: &PayloadKeySet,
) -> anyhow::Result<()> {
let marker = self.execution_payload_marker().await?;
match marker {
None => self.activate_execution_payload_storage(keys).await?,
Some(version) => anyhow::ensure!(
version == EXECUTION_PAYLOAD_PROTOCOL_VERSION,
"Execution payload protection version {version} is newer than supported version {EXECUTION_PAYLOAD_PROTOCOL_VERSION}"
),
}
loop {
let state = self.execution_payload_state().await?.ok_or_else(|| {
anyhow::anyhow!("Execution payload marker exists without durable state")
})?;
validate_execution_payload_state(&state, keys)?;
match state.operation.as_str() {
"migrate" => {
if self
.migrate_execution_payload_batch(keys, EXECUTION_PAYLOAD_BATCH_SIZE)
.await?
{
break;
}View on GitHub (pinned to 18893faf8b)
Solutions
- Upgrade to the release whose EXECUTION_PAYLOAD_PROTOCOL_VERSION matches the stored marker version
- Check the stored version: SELECT version FROM execution_schema_version WHERE component = '<payload component>'
- If a downgrade is truly required, restore a database backup taken with the old version — do not hand-edit the marker
- Confirm you are pointing at the intended database (env/config DATABASE_URL)
Example fix
// before: old binary against upgraded DB
let db = Database::connect(config.postgres_url.as_str()).await?; // panics/errors: version mismatch
// after: pin binary version compatible with the DB, or verify first
let stored: i16 = sqlx::query_scalar(
"SELECT version FROM execution_schema_version WHERE component = $1")
.bind(EXECUTION_PAYLOAD_COMPONENT).fetch_one(&pool).await?;
assert_eq!(stored, EXECUTION_PAYLOAD_PROTOCOL_VERSION, "update the node binary"); Defensive patterns
Strategy: validation
Validate before calling
let stored: Option<i16> = sqlx::query_scalar(
"SELECT version FROM execution_schema_version WHERE component = $1")
.bind(EXECUTION_PAYLOAD_COMPONENT).fetch_optional(&pool).await?;
if let Some(v) = stored {
assert_eq!(v, EXECUTION_PAYLOAD_PROTOCOL_VERSION,
"DB payload protocol {} incompatible with binary {}; update the node",
v, EXECUTION_PAYLOAD_PROTOCOL_VERSION);
} Type guard
fn is_compatible_protocol(stored: Option<i16>, supported: i16) -> bool {
matches!(stored, None | Some(v) if v == supported)
} Try / catch
match ensure_execution_payload_storage(&db, &keys).await {
Err(e) if e.to_string().contains("newer than supported version") => {
eprintln!("DB was upgraded by a newer release; upgrade this node binary before connecting");
std::process::exit(78); // EX_CONFIG
}
other => other?,
} Prevention
- Pin node binary versions per database; never downgrade below the version that last wrote the DB
- Check the stored protocol version in deployment scripts before rollout
- Use separate databases per binary version during canary rollouts
- Alert on protocol-version mismatch in pre-flight health checks
When it happens
Trigger: Calling `ensure_execution_payload_storage` when `execution_payload_marker()` returns Some(version) and version != EXECUTION_PAYLOAD_PROTOCOL_VERSION — i.e. the database was initialized by a newer release with a bumped payload protection protocol and you then started an older binary against the same DB.
Common situations: Downgrade: running a previous release after a newer one upgraded the storage protocol; pointing a test/staging build at a production database initialized by a newer version; hot-swap between builds with different protocol constants.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Unsupported execution payload protection version {version}
- Failed to load active execution intent: {e}
- Failed to start replacement transaction persistence: {e}
- Failed to lock active execution intent {intent_id}: {e}
- Active execution intent {intent_id} was not found
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/470399c34068bde0.
Report an issue: GitHub.