nautechsystems/nautilus_trader · error
Deployment manifest is missing a swap call graph
Error message
Deployment manifest is missing a swap call graph
What it means
After per-edge validation, the manifest must contain at least one call edge with purpose "swap_sell" and at least one with purpose "swap_buy". A deployment without both swap directions cannot be used for the router's two-way swap flow, so validation fails with this error.
Source
Thrown at crates/adapters/blockchain/src/rpc/verification.rs:1422
for address in [caller, target] {
anyhow::ensure!(
contract_addresses.contains(&address),
"Call edge references an unpinned contract"
);
}
anyhow::ensure!(
call_edges.insert((
edge.purpose.as_str(),
caller,
target,
edge.call_type.as_str()
)),
"Deployment manifest contains a duplicate call edge"
);
}
for purpose in ["swap_sell", "swap_buy"] {
anyhow::ensure!(
manifest
.call_edges
.iter()
.any(|edge| edge.purpose == purpose),
"Deployment manifest is missing a swap call graph"
);
}
Ok(())
}
fn validate_identity(identity: &BlockchainProviderIdentity) -> anyhow::Result<()> {
anyhow::ensure!(
!identity.provider_id.trim().is_empty(),
"Provider ID is required"
);
anyhow::ensure!(
!identity.operator_id.trim().is_empty(),
"Provider operator ID is required"View on GitHub (pinned to 18893faf8b)
Solutions
- Add call edges with purpose "swap_sell" and "swap_buy" from the router to the swap-capable contract
- If your generator supports a swap-flow option, enable it so both directions are emitted
- Restore the swap edges from a previously valid manifest for the same deployment
- Verify after editing that call_edges contains at least one edge of each required purpose
Example fix
// before
{"call_edges": [{"purpose": "wrap", ...}, {"purpose": "approve", ...}]}
// after
{"call_edges": [{"purpose": "wrap", ...}, {"purpose": "approve", ...}, {"purpose": "swap_sell", "caller": "0xrouter...", "target": "0xpool...", "call_type": "call"}, {"purpose": "swap_buy", "caller": "0xrouter...", "target": "0xpool...", "call_type": "call"}]} Defensive patterns
Strategy: validation
Validate before calling
for purpose in ["swap_sell", "swap_buy"] {
if !manifest.call_edges.iter().any(|e| e.purpose == purpose) {
return Err(format!("manifest missing a '{purpose}' call edge"));
}
} Try / catch
match validate_deployment_manifest(&manifest) {
Err(e) if e.to_string().contains("missing a swap call graph") => {
eprintln!("Add both swap_sell and swap_buy call edges to the manifest");
}
Err(e) => return Err(e),
Ok(()) => {}
} Prevention
- Use the official generator with the full swap flow enabled so both directions are emitted
- Check manifest completeness (all four purposes) before submission
- Never trim swap edges from template manifests
When it happens
Trigger: Validating a manifest whose call_edges only include "wrap"/"approve" edges (or only one swap direction); this fires even when every individual edge is valid and pinned.
Common situations: Authoring a minimal manifest with just approval edges and forgetting the swap graph; a generator configured for one-directional swaps only; accidentally deleting the swap edges while trimming an existing manifest; copying a template where swap edges were removed as examples.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Pool manifest references an unpinned contract
- Pool fee is invalid
- DEX {dex_id} is not registered in the data client
- `router_addresses` must contain at least one router address
- Quote spend limit for {token_in} -> {token_out} is denominat
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/edefcd0aee6aed0a.
Report an issue: GitHub.