{"record":{"id":"657e4895752b409e","repo":"nautechsystems/nautilus_trader","slug":"cannot-add-settlement-order-client-order-id-e","errorCode":null,"errorMessage":"cannot add settlement order {client_order_id}: {e}","messagePattern":"cannot add settlement order (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/execution/src/matching_engine/settlement.rs","lineNumber":183,"sourceCode":"        for leg in &plan.legs {\n            self.generate_order_accepted(&leg.order, leg.fill.venue_order_id);\n        }\n\n        for leg in plan.legs {\n            self.dispatch_order_event(OrderEventAny::Filled(leg.fill));\n        }\n\n        Ok(())\n    }\n\n    fn option_register_settlement_plan(&self, plan: &OptionSettlementPlan) -> anyhow::Result<()> {\n        for leg in &plan.legs {\n            let client_order_id = leg.order.client_order_id();\n            let mut cache = self.cache.borrow_mut();\n            cache\n                .add_order(leg.order.clone(), leg.fill.position_id, None, false)\n                .map_err(|e| {\n                    anyhow::anyhow!(\"cannot add settlement order {client_order_id}: {e}\")\n                })?;\n            cache\n                .add_venue_order_id(&client_order_id, &leg.fill.venue_order_id, false)\n                .map_err(|e| {\n                    anyhow::anyhow!(\n                        \"cannot claim venue order ID {} for settlement order {client_order_id}: {e}\",\n                        leg.fill.venue_order_id\n                    )\n                })?;\n        }\n        Ok(())\n    }\n\n    fn option_should_exercise(&self, underlying_price: Price) -> bool {\n        let strike = match self.instrument.strike_price() {\n            Some(p) => p.as_decimal(),\n            None => return false,\n        };","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/execution/src/matching_engine/settlement.rs#L165-L201","documentation":"While applying an options settlement plan, the engine registers each settlement leg's order into the cache via add_order. If the cache rejects the order (duplicate client_order_id, missing instrument, inconsistent position_id, etc.), the engine wraps the underlying cache error into this context-rich anyhow error and aborts applying the settlement plan.","triggerScenarios":"option_apply_settlement_plan called twice for the same expiry (duplicate client_order_id already in cache); a settlement leg references a position_id that conflicts with existing cache state; the instrument for the leg is not registered in the cache.","commonSituations":"Replaying settlement plans after a restart without clearing previously registered legs; expired-options handling firing more than once per expiry due to duplicated expiry events; cache snapshots restored mid-settlement.","solutions":["Ensure settlement plans are applied exactly once per expiry — guard with an applied/expiry-set check.","If replaying, clear previously registered settlement orders from the cache or resume from a post-settlement snapshot.","Inspect the wrapped inner error ({e}) to see the precise cache rejection (duplicate ID vs missing instrument vs position mismatch) and fix that cause.","Verify all instruments and positions referenced by plan.legs exist in the cache before applying the plan."],"exampleFix":"// before: applying the same settlement plan twice\nengine.option_apply_settlement_plan(&plan)?; // ok\nengine.option_apply_settlement_plan(&plan)?; // duplicate client_order_id\n// after: track applied expiries\nif applied_expiries.insert(plan.expiry) {\n    engine.option_apply_settlement_plan(&plan)?;\n}","handlingStrategy":"try-catch","validationCode":"// ensure every settlement leg is registrable before applying the plan\nfor leg in &plan.legs {\n    assert!(!cache.order(&leg.order.client_order_id()).is_some(),\n        \"settlement order {} already registered\", leg.order.client_order_id());\n    assert!(cache.instrument(&leg.order.instrument_id()).is_some(),\n        \"instrument {} missing from cache\", leg.order.instrument_id());\n}","typeGuard":"fn plan_applicable(cache: &Cache, plan: &SettlementPlan) -> bool {\n    plan.legs.iter().all(|leg| cache.order(&leg.order.client_order_id()).is_none())\n}","tryCatchPattern":"match engine.option_apply_settlement_plan(&plan) {\n    Err(e) if e.to_string().contains(\"cannot add settlement order\") => {\n        log::error!(\"{e:#}; skipping already-applied settlement plan for expiry {}\", plan.expiry);\n        // treat as applied-once violation; do not retry blindly\n    }\n    other => other,\n}","preventionTips":["Apply each settlement plan exactly once — persist applied expiry markers.","On restart, resume from a post-settlement snapshot rather than replaying settlement events.","Read the wrapped inner cache error to distinguish duplicate IDs from missing instruments."],"tags":["matching-engine","settlement","cache","options","duplicate-registration"],"backgroundTag":"file-already-exists","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}