nautechsystems/nautilus_trader · error

A signed transaction requires exactly one payload representa

Error message

A signed transaction requires exactly one payload representation

What it means

`add_execution_transaction_payload` (backing `add_execution_transaction_hash` and `add_execution_transaction_envelope`) accepts either a raw (plaintext) signed transaction or a sealed (encrypted envelope) transaction, but not both and not neither. `anyhow::ensure!` fires this error when the exclusive-OR check `raw_transaction.is_some() != sealed_transaction.is_some()` fails.

Source

Thrown at crates/adapters/blockchain/src/cache/database.rs:6609

        self.add_execution_transaction_payload(
            intent_id,
            chain_id,
            transaction_hash,
            None,
            Some(sealed_transaction),
        )
        .await
    }

    async fn add_execution_transaction_payload(
        &self,
        intent_id: i64,
        chain_id: u32,
        transaction_hash: &str,
        raw_transaction: Option<&[u8]>,
        sealed_transaction: Option<&[u8]>,
    ) -> anyhow::Result<ExecutionTransactionHashRow> {
        anyhow::ensure!(
            raw_transaction.is_some() != sealed_transaction.is_some(),
            "A signed transaction requires exactly one payload representation"
        );
        let chain_id_db = i32::try_from(chain_id)
            .with_context(|| format!("Chain ID {chain_id} exceeds PostgreSQL INTEGER"))?;
        let mut transaction =
            self.pool.begin().await.map_err(|e| {
                anyhow::anyhow!("Failed to start signed transaction persistence: {e}")
            })?;

        if let Some(envelope) = sealed_transaction {
            let state_row = sqlx::query(
                "SELECT deployment_id, protocol_version, operation, active_key_id \
                 FROM execution_payload_state WHERE component = 'signed_transactions' FOR SHARE",
            )
            .fetch_optional(&mut *transaction)
            .await
            .context("failed to lock execution payload state for protected persistence")?

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass exactly one of `raw_transaction` or `sealed_transaction` as Some and the other as None
  2. Use the public wrappers `add_execution_transaction_hash` (raw) or `add_execution_transaction_envelope` (sealed) instead of calling `add_execution_transaction_payload` directly
  3. Note: if payload protection has been activated in the database (execution_schema_version marker exists), raw persistence is rejected — use the sealed envelope path

Example fix

// before
db.add_execution_transaction_payload(intent_id, chain_id, &hash, Some(raw), Some(sealed)).await?;
// after
db.add_execution_transaction_payload(intent_id, chain_id, &hash, None, Some(sealed)).await?;
Defensive patterns

Strategy: validation

Validate before calling

fn validate_payload_args(raw: Option<&[u8]>, sealed: Option<&[u8]>) -> Result<(), &'static str> {
    match (raw, sealed) {
        (Some(_), None) | (None, Some(_)) => Ok(()),
        _ => Err("pass exactly one of raw_transaction or sealed_transaction"),
    }
}

Try / catch

match validate_payload_args(raw, sealed) {
    Err(msg) => { tracing::error!("{msg}"); return Err(anyhow::anyhow!(msg)); }
    Ok(()) => db.add_execution_transaction_payload(intent_id, chain_id, &hash, raw, sealed).await?,
}

Prevention

When it happens

Trigger: Calling `add_execution_transaction_payload` directly with both `raw_transaction` and `sealed_transaction` set to Some, or with both set to None. The public wrappers (`add_execution_transaction_hash`, `add_execution_transaction_envelope`) cannot trigger it; only misuse of the internal payload API can.

Common situations: A caller migrating code from the raw API to the envelope API passes both payloads 'just in case'; a refactor switches to None-for-both placeholder arguments; test scaffolding constructs the call with both fields populated.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/7129f4c1c438872b. Report an issue: GitHub.