nautechsystems/nautilus_trader · error
Persisted signed transaction is not a complete EIP-2718 enve
Error message
Persisted signed transaction is not a complete EIP-2718 envelope
What it means
decode_signed_transaction calls TxEnvelope::decode_2718_exact, which requires the raw bytes to be exactly one complete EIP-2718 typed-transaction envelope with no trailing bytes. If RLP decoding fails (malformed bytes, truncation, or trailing garbage), the error is replaced with this message. It guards the persisted (sealed/persisted) transaction record's integrity.
Source
Thrown at crates/adapters/blockchain/src/execution/transaction.rs:201
pub(super) struct DecodedSignedTransaction {
pub hash: B256,
pub signer: Address,
pub chain_id: u64,
pub nonce: u64,
pub to: Address,
pub value: U256,
pub input: Bytes,
pub gas_limit: u64,
pub max_fee_per_gas: u128,
pub max_priority_fee_per_gas: u128,
}
/// Decodes and authenticates one complete signed EIP-1559 transaction.
pub(super) fn decode_signed_transaction(
raw_transaction: &[u8],
) -> anyhow::Result<DecodedSignedTransaction> {
let envelope = TxEnvelope::decode_2718_exact(raw_transaction).map_err(|_| {
anyhow::anyhow!("Persisted signed transaction is not a complete EIP-2718 envelope")
})?;
let TxEnvelope::Eip1559(signed) = envelope else {
anyhow::bail!("Persisted signed transaction is not EIP-1559");
};
anyhow::ensure!(
signed.signature().normalize_s().is_none(),
"Persisted transaction signature is not EIP-2 normalized"
);
let signer = signed
.signature()
.recover_address_from_prehash(&signed.signature_hash())
.context("failed to recover persisted transaction signer")?;
let hash = *signed.hash();
let tx = signed.tx();
let TxKind::Call(to) = tx.to else {
anyhow::bail!("Signed transaction creates a contract instead of calling a destination");
};
anyhow::ensure!(View on GitHub (pinned to 18893faf8b)
Solutions
- Hex-dump the raw bytes and confirm the EIP-2718 type byte (0x02 for EIP-1559) is present and the RLP length matches the payload length
- Re-fetch or re-persist the transaction; if bytes are corrupt the original signed tx must be regenerated
- Ensure the caller passes exactly one envelope with no trailing bytes (decode_2718_exact rejects leftovers)
- If legacy transactions must be supported, convert/persist them as EIP-1559 envelopes upstream
Example fix
// before validate_signed_transaction(&legacy_raw_tx_bytes, &intent)?; // legacy tx, no 0x02 prefix // after let envelope_bytes = build_eip1559_envelope(legacy_raw_tx_bytes)?; validate_signed_transaction(&envelope_bytes, &intent)?;
Defensive patterns
Strategy: validation
Validate before calling
fn is_plausible_eip2718_envelope(raw: &[u8]) -> bool {
matches!(raw.first(), Some(0x01 | 0x02))
&& raw.len() >= 2
&& raw.len() <= 131_072 // sanity ceiling before RLP decode
} Type guard
fn looks_like_eip1559(raw: &[u8]) -> bool {
raw.first() == Some(&0x02)
} Try / catch
match validate_signed_transaction(&raw, &intent) {
Ok(()) => (),
Err(e) if e.to_string().contains("complete EIP-2718 envelope") => {
// corrupted or wrong-format persisted bytes; re-fetch or re-persist
}
Err(e) => return Err(e),
} Prevention
- Persist the exact signed envelope bytes and verify length/RLP round-trip after write
- Strip any hex prefix (0x) before decoding raw bytes
- Reject trailing bytes at write time by round-tripping decode_2718_exact on persist
When it happens
Trigger: Calling decode_signed_transaction (via validate_signed_transaction, validate_rpc_transaction_matches_payload, or verify_finalized_transaction_identity) with bytes that are not a valid EIP-2718 envelope: truncated RLP, trailing bytes after the envelope, legacy (non-typed) raw tx bytes without an envelope prefix, or corrupt storage.
Common situations: Persisted tx blob corrupted by a DB migration; caller passes a legacy 0x02-less signed transaction; hex-decoding produced extra bytes; concatenated transaction blobs.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Canonical nonce advanced without an authenticated signer tra
- Receipt verification is locally invalid for transaction {tx_
- Canonical nonce {} is outside the owned reconciliation range
- Missing block number
- Missing transaction hash
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/63e2841818001654.
Report an issue: GitHub.