nautechsystems/nautilus_trader · error

Proxy target role or code hash conflicts with its deployment

Error message

Proxy target role or code hash conflicts with its deployment identity

What it means

For each proxy, the verifier requires its target contract entry to have role == Implementation and a runtime_code_hash byte-for-byte equal (case-insensitively) to the proxy's target_code_hash. This error means the pinned target exists but its declared role or code hash contradicts what the proxy claims, so the proxy would resolve to the wrong or an unverified implementation.

Source

Thrown at crates/adapters/blockchain/src/rpc/verification.rs:1330

            Bytes::from_str(&probe.expected_output)
                .map_err(|_| anyhow::anyhow!("Manifest probe output is invalid"))?;
        }
    }

    for contract in &manifest.contracts {
        let Some(proxy) = &contract.proxy else {
            continue;
        };
        let target =
            Address::from_str(&proxy.target_address).expect("validated proxy target address");
        let target_contract = manifest
            .contracts
            .iter()
            .find(|candidate| Address::from_str(&candidate.address).ok() == Some(target))
            .ok_or_else(|| {
                anyhow::anyhow!("Proxy target has no unique deployment manifest identity")
            })?;
        anyhow::ensure!(
            target_contract.role == BlockchainContractRole::Implementation
                && target_contract
                    .runtime_code_hash
                    .eq_ignore_ascii_case(&proxy.target_code_hash),
            "Proxy target role or code hash conflicts with its deployment identity"
        );
    }

    for required in [
        BlockchainContractRole::Router,
        BlockchainContractRole::Factory,
        BlockchainContractRole::WrappedNative,
        BlockchainContractRole::Quote,
        BlockchainContractRole::Token,
        BlockchainContractRole::Pool,
    ] {
        anyhow::ensure!(
            roles.contains(&required),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set the target contract's role to Implementation and update its runtime_code_hash to the current implementation's runtime code hash
  2. Update proxy.target_code_hash to match the target entry's runtime_code_hash
  3. Regenerate the manifest from deployment tooling and recompute the manifest digest

Example fix

// before
{"address": "0ximpl...", "role": "router", "runtime_code_hash": "0xold..."}
// after
{"address": "0ximpl...", "role": "implementation", "runtime_code_hash": "0xnew..."}
Defensive patterns

Strategy: validation

Validate before calling

fn proxy_target_consistent(manifest: &Manifest) -> bool {
    manifest.contracts.iter().filter_map(|c| c.proxy.as_ref()).all(|p| {
        let target = Address::from_str(&p.target_address).expect("valid target");
        manifest.contracts.iter().find_map(|c| {
            (Address::from_str(&c.address).ok() == Some(target)).then(||
                c.role == Role::Implementation && c.runtime_code_hash.eq_ignore_ascii_case(&p.target_code_hash)
            )
        }) == Some(true)
    })
}

Try / catch

match validate_manifest(&config) {
    Err(e) if e.to_string().contains("role or code hash conflicts") => {
        eprintln!("sync target contract role/runtime_code_hash with proxy.target_code_hash: {e}");
    }
    Err(e) => return Err(e),
    Ok(v) => v,
}

Prevention

When it happens

Trigger: Manifest verification where the contract entry at proxy.target_address has a role other than Implementation, or its runtime_code_hash differs from proxy.target_code_hash — e.g. stale code hash after the implementation was redeployed, or the target entry describes a different contract role (router, pool, etc.).

Common situations: Upgrading the implementation (new code hash) without updating either the target entry or the proxy's target_code_hash; mislabeling the implementation's role in a hand-edited manifest; copying the code hash of the proxy instead of the implementation; hex case handled inconsistently (this check is case-insensitive, so casing alone is not the cause).

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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