{"record":{"id":"945069aa7288ca66","repo":"nautechsystems/nautilus_trader","slug":"oto-parent-not-found","errorCode":null,"errorMessage":"OTO parent not found","messagePattern":"OTO parent not found","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/execution/src/matching_engine/mod.rs","lineNumber":2840,"sourceCode":"                if let Some(expiration_ns) = self.instrument.expiration_ns()\n                    && self.clock.borrow().timestamp_ns() >= expiration_ns\n                {\n                    break 'validate Some(\n                        format!(\n                            \"Contract {} has expired, expiration {expiration_ns}\",\n                            self.instrument.id(),\n                        )\n                        .into(),\n                    );\n                }\n            }\n\n            // Contingent orders checks\n            if self.config.support_contingent_orders {\n                if let Some(parent_order_id) = order.parent_order_id() {\n                    let parent_order = match self.order_snapshot(parent_order_id) {\n                        Some(o) if o.contingency_type() == Some(ContingencyType::Oto) => o,\n                        _ => panic!(\"OTO parent not found\"),\n                    };\n                    let parent_filled_qty = parent_order.filled_qty();\n\n                    if parent_order.status() == OrderStatus::Rejected && order.is_open() {\n                        break 'validate Some(\n                            format!(\"Rejected OTO order from {parent_order_id}\").into(),\n                        );\n                    } else if parent_filled_qty.is_zero()\n                        || (self.config.oto_full_trigger\n                            && parent_filled_qty < parent_order.quantity())\n                    {\n                        log::info!(\n                            \"Pending OTO order {} triggers from {parent_order_id}\",\n                            order.client_order_id(),\n                        );\n                        return;\n                    }\n                }","sourceCodeStart":2822,"sourceCodeEnd":2858,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/execution/src/matching_engine/mod.rs#L2822-L2858","documentation":"During order validation the matching engine found that an order has a parent_order_id, but the parent order either is missing from the cache or is not an OTO (One-Triggers-Other) contingent order. Because contingent-order bookkeeping depends on a valid OTO parent, the engine panics — the child order's contingency chain is broken. This is a defensive invariant protecting OTO lifecycle handling.","triggerScenarios":"Submitting or validating an order carrying parent_order_id where order_snapshot(parent_order_id) returns None or a parent whose contingency_type != ContingencyType::Oto, with config.support_contingent_orders enabled.","commonSituations":"Resubmitting/repairing an OTO child order after the parent was purged from the cache; manually constructing an order with parent_order_id set to an unrelated order; mixing contingently-linked order state across node restarts with a non-persistent cache.","solutions":["Ensure the OTO parent order exists in the matching engine cache before submitting the child (submit parent first).","Verify the parent's contingency_type is actually Oto; fix order construction so parent_order_id is only set on genuine OTO children.","Enable cache persistence or rebuild contingent chains on startup so parents survive restarts.","Reject/fix inbound orders whose parent_order_id cannot be resolved instead of forwarding them to the engine."],"exampleFix":"// before\nchild.parent_order_id = Some(random_id);\n// after\nassert_eq!(parent.contingency_type(), Some(ContingencyType::Oto));\nchild.parent_order_id = Some(parent.client_order_id()); // genuine OTO parent, cached first","handlingStrategy":"validation","validationCode":"// before submitting an OTO child\nlet parent = cache.order(&parent_id);\nlet valid = matches!(parent, Some(o) if o.contingency_type() == Some(ContingencyType::Oto));\nif !valid { return Err(anyhow!(\"OTO parent {parent_id} missing or not OTO\")); }","typeGuard":"fn is_cached_oto_parent(cache: &Cache, id: &ClientOrderId) -> bool {\n    matches!(cache.order(id), Some(o) if o.contingency_type() == Some(ContingencyType::Oto))\n}","tryCatchPattern":null,"preventionTips":["Submit OTO parents before children and keep parents cached for the chain's lifetime.","Only set parent_order_id on orders whose parent really is an OTO order.","Use cache persistence so contingent chains survive restarts.","Reject inbound orders with unresolvable parent_order_id at the client boundary."],"tags":["rust","matching-engine","contingent-orders","panic"],"backgroundTag":"entity-not-found","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}