linera-io/linera-protocol · critical · EvmExecutionError

Incorrect ApplicationId

Error message

Incorrect ApplicationId

What it means

Raised by ContractDatabase::create_new_contract when registering a freshly created EVM contract as a Linera application: the application id derived from the contract's EVM address (address_to_user_application_id) must equal the id the runtime assigned via create_application(module_id, ...). Linera derives application ids deterministically; a mismatch means the EVM address under which the contract was created does not map to the application the runtime registered — an address-derivation collision or non-determinism in the creation path (e.g. CREATE vs CREATE2 divergence, or an address already hosting another application).

Source

Thrown at linera-execution/src/evm/database.rs:697

    ) -> Result<(), ExecutionError> {
        let application_id = address_to_user_application_id(address);
        let mut argument = ALREADY_CREATED_CONTRACT_SELECTOR.to_vec();
        argument.extend(bcs::to_bytes(account)?);
        let evm_instantiation = EvmInstantiation {
            value: U256::ZERO,
            argument,
        };
        let argument = serde_json::to_vec(&evm_instantiation)?;
        let parameters = JSON_EMPTY_VECTOR.to_vec(); // No constructor
        let required_application_ids = Vec::new();
        let mut runtime = self.inner.runtime.lock().unwrap();
        let created_application_id = runtime.create_application(
            module_id,
            parameters,
            argument,
            required_application_ids,
        )?;
        ensure!(
            application_id == created_application_id,
            EvmExecutionError::IncorrectApplicationId
        );
        Ok(())
    }

    /// Commits the changes to another contract.
    /// This is done by doing a call application.
    fn commit_remote_contract(
        &self,
        address: Address,
        account: &revm_state::Account,
    ) -> Result<(), ExecutionError> {
        let application_id = address_to_user_application_id(address);
        let mut argument = COMMIT_CONTRACT_CHANGES_SELECTOR.to_vec();
        argument.extend(bcs::to_bytes(account)?);
        let mut runtime = self.inner.runtime.lock().unwrap();
        runtime.try_call_application(false, application_id, argument)?;

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Reproduce creation on a devnet and log both ids (derived-from-address vs created) to see the divergence
  2. Use a different creation path (plain CREATE instead of CREATE2, or a fresh salt) so the address derivation matches the runtime's expectation
  3. Align the contract's deployment toolchain with the current linera-protocol version
  4. Report with bytecode and creation transaction if the mismatch reproduces on current versions
Defensive patterns

Strategy: try-catch

Type guard

fn is_incorrect_application_id(err: &ExecutionError) -> bool {
    matches!(err, ExecutionError::EvmError(evm_error!::IncorrectApplicationId))
}

Try / catch

match client.execute_operations(ops, vec![]).await {
    Err(e) if is_incorrect_application_id(&e) => {
        // Deterministic address derivation diverged; stop and file a report with bytecode + tx.
        return Err(anyhow::anyhow!("EVM address did not map to the registered application id: {e}"));
    }
    other => other,
}

Prevention

When it happens

Trigger: Contract creation where the EVM CREATE/CREATE2 address computation differs from what the bridge derives; deploying a contract at an address that already maps to a different application id; runtime/application-id derivation changes across protocol versions.

Common situations: Solidity factories using CREATE2 with salts after bridge upgrades; running old bytecode against a new linera-execution; adversarial inputs engineered to collide with existing application addresses.

Related errors


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