linera-io/linera-protocol · error · EvmExecutionError

The function {0} is being called but is missing from the byt

Error message

The function {0} is being called but is missing from the bytecode API

What it means

Before the system invokes one of the Linera base-contract functions on an EVM module (execute_message, process_streams, summarize_events), ensure_selector_presence scans the deployed bytecode for the PUSH4 + selector byte sequence (has_selector). If the sequence is absent the module does not implement that function and the call fails with MissingFunction instead of executing a call that would revert or misbehave.

Source

Thrown at linera-execution/src/evm/inputs.rs:204

}

pub(crate) fn ensure_message_length(
    actual_length: usize,
    min_length: usize,
) -> Result<(), EvmExecutionError> {
    ensure!(
        actual_length >= min_length,
        EvmExecutionError::OperationIsTooShort
    );
    Ok(())
}

pub(crate) fn ensure_selector_presence(
    module: &[u8],
    selector: &[u8],
    fct_name: &str,
) -> Result<(), EvmExecutionError> {
    ensure!(
        has_selector(module, selector),
        EvmExecutionError::MissingFunction(fct_name.to_string())
    );
    Ok(())
}

pub(crate) fn has_selector(module: &[u8], selector: &[u8]) -> bool {
    let push4 = 0x63; // An EVM instruction
    let mut vec = vec![push4];
    vec.extend(selector);
    module.windows(5).any(|window| window == vec)
}

pub(crate) fn get_revm_instantiation_bytes(value: Vec<u8>) -> Vec<u8> {
    use alloy_primitives::Bytes;
    use alloy_sol_types::{sol, SolCall};
    sol! {
        function instantiate(bytes value);

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Inherit the Linera EVM base contract or manually implement execute_message(bytes), process_streams(...) and summarize_events(...) so their selectors exist in the deployed bytecode
  2. Before publishing, scan the bytecode for each required PUSH4 + selector sequence (same check as has_selector in linera-execution/src/evm/inputs.rs:211)
  3. Confirm you published the correct blob type for each side (contract vs service bytecode)
  4. Recompile against the current Linera Solidity SDK so the ABI signatures match

Example fix

// before: plain contract, no Linera entry points
contract MyApp { function doThing() external {} }

// after: inherit the base app so required selectors exist in bytecode
contract MyApp is LineraApp {
    function execute_message(bytes calldata value) external { /* ... */ }
    function process_streams(StreamUpdate[] calldata streams) external { /* ... */ }
    function summarize_events(StreamUpdate[] calldata streams) external { /* ... */ }
}
Defensive patterns

Strategy: validation

Validate before calling

// Mirror of has_selector: check the published bytecode before deploying (Rust)
fn has_selector(module: &[u8], selector: &[u8]) -> bool {
    let mut pattern = vec![0x63u8]; // PUSH4
    pattern.extend_from_slice(selector);
    module.windows(5).any(|w| w == pattern)
}

let required: &[(&[u8], &str)] = &[
    (EXECUTE_MESSAGE_SELECTOR, "execute_message"),
    (PROCESS_STREAMS_SELECTOR, "process_streams"),
    (SUMMARIZE_EVENTS_SELECTOR, "summarize_events"),
];
for (sel, name) in required {
    assert!(has_selector(&contract_bytecode, sel), "missing {name} in bytecode");
}
publish(contract_bytecode)?;

Type guard

fn is_missing_function(err: &ExecutionError) -> Option<&str> {
    match err {
        ExecutionError::EvmError(EvmExecutionError::MissingFunction(name)) => Some(name),
        _ => None,
    }
}

Try / catch

match runtime.receive_message(msg).await {
    Ok(()) => {}
    Err(ref e) if is_missing_function(e).is_some() => {
        log::warn!("bytecode lacks {:?}; redeploy with the base contract", is_missing_function(e));
        return Err(e.clone()); // deterministic failure: do not retry
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Publishing an EVM contract whose runtime bytecode contains no PUSH4 for execute_message(bytes), process_streams(...), or summarize_events(...), then receiving a message or stream update that routes into execute_message/process_streams, or a checkpoint that calls summarize_events.

Common situations: Deploying a plain Ethereum contract that does not inherit the Linera EVM base contract; publishing ServiceBytecode where ContractBytecode/EvmBytecode is expected; upgrading the Linera Solidity SDK where the expected function signature changed; aggressive optimizer or linker settings stripping the entry points.

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/ec64f5f56c439b51. Report an issue: GitHub.