nautechsystems/nautilus_trader · error

Deployment manifest version does not match its configured id

Error message

Deployment manifest version does not match its configured identity

What it means

The validator compares the deployment manifest's embedded `version` field against the separately configured `manifest_version`. If they differ, the configured identity and the manifest content disagree, which would let a stale or swapped manifest masquerade under the configured version. Validation fails with this message.

Source

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

    anyhow::ensure!(
        anchor.max_head_skew_blocks != 0
            && anchor.max_head_age_secs != 0
            && anchor.max_future_drift_secs != 0,
        "Chain head skew, age, and future-drift limits must be nonzero"
    );
    anyhow::ensure!(
        !config.manifest_version.trim().is_empty(),
        "Deployment manifest version is required"
    );
    let manifest_digest = B256::from_str(&config.manifest_digest).map_err(|_| {
        anyhow::anyhow!("Deployment manifest digest must contain 32 hexadecimal bytes")
    })?;
    anyhow::ensure!(
        manifest_digest != B256::ZERO,
        "Deployment manifest digest must be nonzero"
    );
    let manifest = &config.deployment_manifest;
    anyhow::ensure!(
        manifest.version == config.manifest_version,
        "Deployment manifest version does not match its configured identity"
    );
    anyhow::ensure!(
        manifest.chain_id == anchor.chain_id && manifest.chain_name == anchor.chain_name,
        "Deployment manifest chain identity does not match the chain anchor"
    );
    let canonical_manifest = serde_json::to_vec(manifest)
        .map_err(|_| anyhow::anyhow!("Failed to serialize the deployment manifest"))?;
    anyhow::ensure!(
        keccak256(canonical_manifest) == manifest_digest,
        "Deployment manifest digest does not match its canonical content"
    );
    anyhow::ensure!(
        !manifest.contracts.is_empty() && !manifest.tokens.is_empty() && !manifest.pools.is_empty(),
        "Deployment manifest contracts, tokens, and pools are required"
    );
    let mut contract_addresses = HashSet::new();

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Make `config.manifest_version` exactly equal `deployment_manifest.version` (prefer deriving one from the other).
  2. Regenerate the manifest for the new version and recompute the digest, then update the config.
  3. Pin both values from a single source (build script or manifest artifact) so they cannot drift.

Example fix

// before
let config = DeploymentConfig { manifest_version: "v1.3.0".into(), ..config }; // manifest.version == "v1.2.0"
// after
let config = DeploymentConfig { manifest_version: manifest.version.clone(), ..config };
Defensive patterns

Strategy: validation

Validate before calling

assert_eq!(
    config.manifest_version,
    config.deployment_manifest.version,
    "configured manifest_version must equal the manifest's own version"
);

Prevention

When it happens

Trigger: Validating a DeploymentConfig where `config.manifest_version != config.deployment_manifest.version` (e.g. config bumped to a new version but the manifest file was not regenerated).

Common situations: Partial release rollout: config updated, manifest artifact stale; hotfix edits the manifest version directly but forgets the config; two environments sharing one manifest with different configured versions.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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