EEVM.Error (eevm v0.1.0)

Copy Markdown View Source

Reference for all error atoms used across the EEVM codebase.

EEVM uses tagged tuples for error handling: {:error, reason} or {:error, reason, state}. This module documents every error reason atom and which modules produce them; reason/0 is their union and message/1 describes one.

Reasons are plain atoms, so they match in case and with directly. They are part of the public API: a new reason is a minor change, and renaming or removing one is a breaking change. The only composite reason is {:tx_failed, index, reason} from block execution.

Execution Errors

These errors halt the current execution frame:

ErrorSourceMeaning
:stack_underflowEEVM.Interpreter (pre-dispatch check), EEVM.Interpreter.StackAttempted to pop/peek from an empty stack
:stack_overflowEEVM.Interpreter (pre-dispatch check), EEVM.Interpreter.StackAttempted to push onto a full stack (1,024 elements)
:out_of_gasEEVM.Interpreter.MachineStateGas consumed exceeds available gas
:invalid_jump_destinationEEVM.InterpreterJUMP/JUMPI target is not a JUMPDEST
:static_state_modificationEEVM.Interpreter, EEVM.Interpreter.Instructions.System.CallsState-mutating opcode or value-bearing CALL inside a STATICCALL frame (EIP-214)
:return_data_out_of_boundsEEVM.Interpreter.Instructions.Environment.DataRETURNDATACOPY reads past the end of the return data buffer
:initcode_too_largeEEVM.Interpreter.Instructions.System.CreationCREATE/CREATE2 initcode exceeds 49,152 bytes (EIP-3860)
:insufficient_balanceEEVM.Database.transfer/4Transfer amount exceeds account balance
:invalid_opcodeEEVM.InterpreterINVALID (0xFE) or an opcode the fork doesn't define
:create_collisionEEVM.Handler.ExecutionA creation transaction targets an address that already has code, a nonce, or storage (EIP-684, EIP-7610)
:code_size_limit_exceededEEVM.Handler.ExecutionDeployed code is over 24,576 bytes (EIP-170)
:invalid_code_prefixEEVM.Handler.ExecutionDeployed code starts with 0xEF (EIP-3541, from London)

Precompile Errors

Returned by precompiled contract implementations:

ErrorSourceMeaning
:out_of_gasAll precompilesGas limit insufficient for the operation
:invalid_inputBN256, BLS12-381, Blake2F, KZG, ModExp (EIP-7823)Input data has wrong length or format
:invalid_pointBN256, BLS12-381Elliptic curve point not on the curve or not in the subgroup
:invalid_versioned_hashKZGVersioned hash doesn't match expected format
:invalid_field_elementKZGField element is not in the valid range
:proof_verification_failedKZGKZG proof verification returned false
:not_implementedEEVM.PrecompilesPrecompile address has no implementation

Transaction Decoding and Signature Errors

Returned by EEVM.Transaction.Envelope.decode/1 and EEVM.Transaction.Signer, and so by EEVM.Handler.execute/4 when it is given raw bytes or a bad signature.

ErrorMeaning
:invalid_transaction_inputThe transaction is neither a transaction struct nor a binary
:empty_inputThe encoded transaction is empty
:invalid_typeThe EIP-2718 type byte isn't a known transaction type
:hex_stringThe bytes are a 0x-prefixed hex string; decode them with EEVM.bytes/1
:invalid_rlpThe payload isn't valid RLP
:invalid_rlp_integerAn integer field has leading zero bytes (non-canonical RLP)
:invalid_fieldsThe RLP list has the wrong number or shape of fields for its type
:invalid_vA legacy v is neither 27/28 nor an EIP-155 value (35 or more)
:invalid_chain_idThe transaction was signed for another chain: a typed transaction's chain_id, or the chain id in an EIP-155 legacy v, differs from the config's
:invalid_signaturer, s, or y_parity is out of range (including high s, EIP-2), or no key recovers
:invalid_private_keyEEVM.Transaction.Signer.sign/3 got a key that is zero or not below the curve order

Transaction Validation Errors

Returned by EEVM.transact/4 (and EEVM.Handler.execute/4) before any state changes; EEVM.Transaction.Validator runs the checks. They run in the order listed and the first failure wins.

ErrorMeaning
:tx_type_not_supportedSet-code (type 4) transaction before Prague (EIP-7702)
:set_code_tx_no_creationSet-code transaction has no to address (EIP-7702)
:empty_authorization_listSet-code transaction carries no authorizations (EIP-7702)
:invalid_authorizationAn authorization field is out of range, such as a nonce of 2^64 or more (EIP-7702)
:intrinsic_gas_too_lowgas_limit is below the intrinsic gas (or, from Prague, the EIP-7623 calldata floor)
:gas_limit_exceeds_capgas_limit is above 2^24 (EIP-7825, from Osaka)
:gas_limit_exceeds_blockgas_limit is above the block gas limit
:nonce_too_lownonce is below the sender's account nonce
:nonce_too_highnonce is above the sender's account nonce
:nonce_is_maxnonce is 2^64 - 1, so the sender's nonce can't be incremented (EIP-2681)
:priority_fee_above_max_feemax_priority_fee_per_gas exceeds max_fee_per_gas (EIP-1559)
:max_fee_below_basefeemax_fee_per_gas, or gas_price for legacy and EIP-2930 transactions, is below the block base fee (EIP-1559)
:insufficient_balanceBalance can't cover gas_limit * max price + blob gas * max_fee_per_blob_gas + value
:sender_not_eoaSender has code other than a delegation designator (EIP-3607, EIP-7702)
:blob_tx_no_creationBlob transaction has no to address (EIP-4844)
:no_blob_dataBlob transaction carries no blob hashes (EIP-4844)
:too_many_blobsBlob transaction carries more blobs than a block allows (EIP-4844), or more than 6 (EIP-7594)
:invalid_versioned_hashA blob versioned hash doesn't start with 0x01 (EIP-4844)
:blob_fee_too_lowmax_fee_per_blob_gas is below the block blob base fee (EIP-4844)
:initcode_too_largeContract-creation data exceeds 49,152 bytes (EIP-3860)
:effective_gas_price_below_basefeeThe effective gas price is below the block base fee (checked again when charging the sender)

Block Header Validation Errors

Returned by EEVM.Block.validate/3, execute/4, and build/4 when a header is not a valid successor of its parent; EEVM.Block.HeaderValidator runs the checks. They run in the order listed and the first failure wins.

ErrorMeaning
:unknown_parentparent_hash doesn't match the parent header's hash
:invalid_block_numbernumber isn't the parent's number plus one
:invalid_timestamptimestamp isn't greater than the parent's
:extra_data_too_bigextra_data is longer than 32 bytes
:invalid_gas_limitgas_limit is below 5,000 or moves by parent_gas_limit / 1024 or more
:gas_limit_too_biggas_limit exceeds the signed 64-bit maximum
:invalid_base_feebase_fee_per_gas differs from the value derived from the parent (EIP-1559, from London)
:invalid_difficultydifficulty is 0 before Paris or not 0 from Paris (EIP-3675)
:invalid_noncenonce isn't eight zero bytes (EIP-3675, from Paris)
:invalid_ommers_hashommers_hash isn't the empty-list hash (EIP-3675, from Paris)
:missing_header_fieldsA field the fork defines (base_fee_per_gas, withdrawals_root, the blob fields, parent_beacon_block_root, requests_hash) is nil
:unexpected_header_fieldsA field from a later fork is set
:invalid_blob_gas_usedblob_gas_used isn't a multiple of 131,072 or exceeds the fork's per-block maximum (EIP-4844, EIP-7691)
:invalid_excess_blob_gasexcess_blob_gas differs from the value derived from the parent (EIP-4844, EIP-7918 from Osaka)

Block Errors

Returned by EEVM.Block.decode/1, validate/3, execute/4, and build/4, in addition to every header validation error above.

ErrorMeaning
:invalid_block_encodingThe bytes aren't a canonical RLP block
:simulation_configThe EEVM.Config sets a simulation switch (disable_*), which blocks never run under
:rlp_block_size_exceededThe encoded block is over 8,388,608 bytes (EIP-7934, from Osaka)
:invalid_transactions_roottransactions_root doesn't commit to the block's transactions
:invalid_withdrawals_rootwithdrawals_root doesn't commit to the withdrawals, or withdrawals are present before Shanghai or missing after
:invalid_ommers_hashommers_hash doesn't commit to the block's ommers
:invalid_blob_gas_usedblob_gas_used differs from the transactions' total blob gas
{:tx_failed, index, reason}Transaction index (0-based) was rejected: reason is an EEVM.Handler error, or :gas_allowance_exceeded when its gas limit exceeds the gas left in the block
:invalid_gas_usedgas_used differs from the gas the transactions used
:invalid_logs_bloomlogs_bloom differs from the receipts' combined bloom
:invalid_receipts_rootreceipts_root differs from the receipts' root
:invalid_state_rootstate_root differs from the post-block state
:invalid_deposit_event_layoutA deposit contract DepositEvent log isn't the 576-byte EIP-6110 layout (from Prague)
:system_contract_emptyThe EIP-7002 or EIP-7251 request contract has no code (from Prague); a new chain gets it from EEVM.SystemContracts
:system_contract_call_failedThe end-of-block call to the EIP-7002 or EIP-7251 request contract failed (from Prague)
:invalid_requests_hashrequests_hash differs from the EIP-7685 hash of the block's requests (from Prague)

State Errors

A backend callback that returns {:error, reason} aborts EEVM.run/2, EEVM.transact/4, and EEVM.Block.execute/4 and build/4 with {:error, {:database, reason}}; see EEVM.Database.

ErrorSourceMeaning
:commit_not_supportedEEVM.Database.commit/1The backend's commit/2 returned {:error, :unsupported}; apply changes/1 yourself

ABI Errors

ErrorSourceMeaning
:invalid_abi_dataEEVM.ABI.decode/2, EEVM.ABI.decode_log/2The data doesn't hold valid values of the given types
:event_mismatchEEVM.ABI.decode_log/2The log's first topic or topic count doesn't match the event signature

Registry Errors

ErrorSourceMeaning
:unknown_opcodeEEVM.Interpreter.Instructions.RegistryOpcode byte has no known metadata

Execution status

EEVM.CallResult and EEVM.TransactionResult report how execution ended in status, which is not an error:

  • :success — STOP or RETURN
  • :revert — REVERT; the call's state changes are undone and unused gas is returned
  • {:halt, reason} — an exceptional halt that consumes all the call's gas, with an execution or precompile error from this module as reason

Summary

Types

Why execution halted exceptionally: the reason in {:halt, reason}.

Every error reason eevm returns.

Functions

Returns a short human-readable description of reason.

Types

block_error()

@type block_error() ::
  :invalid_block_encoding
  | :simulation_config
  | :rlp_block_size_exceeded
  | header_validation_error()
  | :invalid_transactions_root
  | :invalid_withdrawals_root
  | :invalid_blob_gas_used
  | {:tx_failed, non_neg_integer(), atom()}
  | :invalid_gas_used
  | :invalid_logs_bloom
  | :invalid_receipts_root
  | :invalid_state_root
  | :invalid_deposit_event_layout
  | :system_contract_empty
  | :system_contract_call_failed
  | :invalid_requests_hash

decode_error()

@type decode_error() ::
  :invalid_transaction_input
  | :empty_input
  | :invalid_type
  | :hex_string
  | :invalid_rlp
  | :invalid_rlp_integer
  | :invalid_fields
  | :invalid_v
  | :invalid_chain_id
  | :invalid_signature
  | :invalid_private_key

execution_error()

@type execution_error() ::
  :stack_underflow
  | :stack_overflow
  | :out_of_gas
  | :invalid_jump_destination
  | :static_state_modification
  | :return_data_out_of_bounds
  | :initcode_too_large
  | :insufficient_balance
  | :invalid_opcode
  | :create_collision
  | :code_size_limit_exceeded
  | :invalid_code_prefix

halt_reason()

@type halt_reason() :: execution_error() | precompile_error()

Why execution halted exceptionally: the reason in {:halt, reason}.

header_validation_error()

@type header_validation_error() ::
  :unknown_parent
  | :invalid_block_number
  | :invalid_timestamp
  | :extra_data_too_big
  | :invalid_gas_limit
  | :gas_limit_too_big
  | :invalid_base_fee
  | :invalid_difficulty
  | :invalid_nonce
  | :invalid_ommers_hash
  | :missing_header_fields
  | :unexpected_header_fields
  | :invalid_blob_gas_used
  | :invalid_excess_blob_gas

precompile_error()

@type precompile_error() ::
  :out_of_gas
  | :invalid_input
  | :invalid_point
  | :invalid_versioned_hash
  | :invalid_field_element
  | :proof_verification_failed
  | :not_implemented

reason()

@type reason() ::
  execution_error()
  | precompile_error()
  | :unknown_opcode
  | :commit_not_supported
  | :invalid_abi_data
  | :event_mismatch
  | decode_error()
  | transaction_validation_error()
  | block_error()

Every error reason eevm returns.

transaction_validation_error()

@type transaction_validation_error() ::
  :tx_type_not_supported
  | :set_code_tx_no_creation
  | :empty_authorization_list
  | :invalid_authorization
  | :intrinsic_gas_too_low
  | :gas_limit_exceeds_cap
  | :gas_limit_exceeds_block
  | :nonce_too_low
  | :nonce_too_high
  | :nonce_is_max
  | :priority_fee_above_max_fee
  | :max_fee_below_basefee
  | :insufficient_balance
  | :sender_not_eoa
  | :blob_tx_no_creation
  | :no_blob_data
  | :too_many_blobs
  | :invalid_versioned_hash
  | :blob_fee_too_low
  | :initcode_too_large
  | :effective_gas_price_below_basefee

Functions

message(error)

@spec message(reason() | :gas_allowance_exceeded | EEVM.TransactionError.t() | term()) ::
  String.t()

Returns a short human-readable description of reason.

Examples

iex> EEVM.Error.message(:nonce_too_low)
"nonce too low"
iex> EEVM.Error.message({:tx_failed, 2, :intrinsic_gas_too_low})
"transaction 2 failed: gas limit below the intrinsic gas"
iex> EEVM.Error.message({:database, :econnrefused})
"database read failed: :econnrefused"