nautechsystems/nautilus_trader · error · anyhow::Error
Execution payload rewrap state is missing
Error message
Execution payload rewrap state is missing
What it means
During execution-payload key rewrapping, `rewrap_execution_payload_batch` locks and reads the singleton `execution_payload_state` row for component 'signed_transactions' (`SELECT ... FOR UPDATE`). This error is raised when that row does not exist. The library requires the state row to have been initialized by `begin_execution_payload_rewrap` (or equivalent setup) before batch rewrapping can proceed, since it tracks the operation ('ready'/'rewrap') and active key ID in it.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:5421
async fn rewrap_execution_payload_batch(
&self,
keys: &PayloadKeySet,
batch_size: i64,
) -> anyhow::Result<bool> {
let mut transaction = self
.pool
.begin()
.await
.context("failed to start execution payload rewrap batch")?;
lock_execution_payload_operation(&mut transaction).await?;
let state_row = sqlx::query(
"SELECT deployment_id, protocol_version, operation, active_key_id \
FROM execution_payload_state WHERE component = 'signed_transactions' FOR UPDATE",
)
.fetch_optional(&mut *transaction)
.await
.context("failed to lock execution payload rewrap state")?
.ok_or_else(|| anyhow::anyhow!("Execution payload rewrap state is missing"))?;
let state = execution_payload_state_from_row(&state_row)?;
validate_execution_payload_state(&state, keys)?;
if state.operation == "ready" {
transaction
.commit()
.await
.context("failed to complete execution payload rewrap")?;
return Ok(true);
}
anyhow::ensure!(
state.operation == "rewrap",
"Execution payload storage is not rewrapping"
);
let rows = sqlx::query_as::<_, ExecutionTransactionHashRow>(
"
SELECT
id, intent_id, chain_id, transaction_hash, payload_expected,
raw_transaction, sealed_transaction, status, block_number, block_hash,View on GitHub (pinned to 18893faf8b)
Solutions
- Run the database initialization/migration path that inserts the `execution_payload_state` row for component 'signed_transactions' (via `begin_execution_payload_rewrap` or the schema bootstrap) before starting the rewrap.
- Check that the adapter is connecting to the intended database/schema — a wrong DATABASE_URL can point at an uninitialized database.
- If the row was deleted accidentally, insert it manually with deployment_id/protocol_version matching the configured key set, operation='ready', and the current active_key_id.
- Verify schema version: apply any pending migrations so the `execution_payload_state` table and its seed row exist.
Example fix
// before: rewrap called directly on an uninitialized DB rewrap_execution_payload_batch(&keys, batch_size).await?; // after: ensure state is initialized first (inserts the state row if absent) begin_execution_payload_rewrap(&keys).await?; rewrap_execution_payload_batch(&keys, batch_size).await?;
Defensive patterns
Strategy: validation
Validate before calling
let state = sqlx::query("SELECT deployment_id, protocol_version, operation, active_key_id FROM execution_payload_state WHERE component = 'signed_transactions'")
.fetch_optional(&mut *tx).await?;
if state.is_none() {
// initialize via begin_execution_payload_rewrap / schema bootstrap before proceeding
return Err(anyhow!("execution_payload_state row missing; run initialization first"));
} Prevention
- Always run schema migrations plus the execution-payload state bootstrap on new environments before starting the adapter.
- Add a startup health check that asserts the `execution_payload_state` row exists for component 'signed_transactions'.
- Never manually delete rows from `execution_payload_state`; use the provided maintenance APIs.
- Pin DATABASE_URL per environment and validate connectivity to the correct schema on boot.
When it happens
Trigger: Calling the rewrap flow (which invokes `rewrap_execution_payload_batch`) against a database where `execution_payload_state` has no row with component='signed_transactions' — e.g. a freshly provisioned database whose migration/initialization step was skipped, or a row deleted manually or by a partial migration.
Common situations: Pointing the adapter at an empty/new Postgres schema created without running the execution-payload state initialization; restoring a partial backup that omitted the state table's row; manual SQL cleanup that deleted the bookkeeping row; running a newer adapter version against an old database that predates the `execution_payload_state` table.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Execution payload storage is not rewrapping
- Execution payload rewrap left {remaining} row(s)
- Execution payload storage is in {operation} maintenance; com
- Execution payload protection is active, but no payload key i
- Execution payload storage is in {operation} maintenance, not
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/411e370d1092d9ac.
Report an issue: GitHub.