{"record":{"id":"85943741dd7f01e0","repo":"nautechsystems/nautilus_trader","slug":"missing-persistence-type-for-order-update","errorCode":null,"errorMessage":"missing persistence type for order update {}","messagePattern":"missing persistence type for order update (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/betfair/src/stream/parse.rs","lineNumber":890,"sourceCode":"    if let Some(lsrc) = uo.lsrc {\n        report.cancel_reason = Some(lsrc.to_string());\n    }\n\n    Ok(report)\n}\n\nfn parse_stream_time_in_force(uo: &UnmatchedOrder) -> anyhow::Result<TimeInForce> {\n    match uo.pt {\n        Some(persistence_type) => Ok(TimeInForce::from(persistence_type)),\n        None if matches!(\n            uo.ot,\n            crate::common::enums::StreamingOrderType::LimitOnClose\n                | crate::common::enums::StreamingOrderType::MarketOnClose\n        ) =>\n        {\n            Ok(TimeInForce::AtTheClose)\n        }\n        None => anyhow::bail!(\"missing persistence type for order update {}\", uo.id),\n    }\n}\n\nfn stream_order_quantity(uo: &UnmatchedOrder) -> Decimal {\n    if uo.s > Decimal::ZERO {\n        return uo.s;\n    }\n\n    let lifecycle_qty = uo.sm.unwrap_or(Decimal::ZERO)\n        + uo.sr.unwrap_or(Decimal::ZERO)\n        + uo.sc.unwrap_or(Decimal::ZERO)\n        + uo.sl.unwrap_or(Decimal::ZERO)\n        + uo.sv.unwrap_or(Decimal::ZERO);\n\n    if lifecycle_qty > Decimal::ZERO {\n        return lifecycle_qty;\n    }\n","sourceCodeStart":872,"sourceCodeEnd":908,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/betfair/src/stream/parse.rs#L872-L908","documentation":"When converting a Betfair streaming order update into a Nautilus order-status report, the parser maps the order's persistence type (LIMIT order persistence: LAPSE vs PERSIST) to a TimeInForce. If the UnmatchedOrder carries no persistence value, the mapping has nothing to translate and the parser bails with the order id. The adapter cannot represent the update faithfully without it.","triggerScenarios":"Receiving an orderChangeMessage / unmatched order (type Limit) whose persistence field is absent — e.g. via an out-of-order change message (conflate/heartbeat loss of the initial image) or an exchange payload lacking the field for this order type.","commonSituations":"Connecting to the Betfair stream with conflation enabled so the initial full order image is missed; Betfair changing/omitting persistence on certain order types (e.g. SP or market-on-close orders reaching an unexpected branch); parsing order updates right after reconnect without a resubscribe snapshot.","solutions":["Re-establish a clean stream snapshot (resubscribe to order changes) so the full order image with persistence is received.","Check the order's type in the update: only LIMIT orders should reach this branch; ensure SP/IOC-style orders are handled by their own mappings.","If the exchange legitimately omits persistence, default it explicitly (e.g. treat as LAPSE/Gtc) instead of failing, or update the adapter mapping for that order type.","Verify the adapter's parse_stream_time_in_force covers all StreamingOrderType variants your account can place."],"exampleFix":"// before\nNone => anyhow::bail!(\"missing persistence type for order update {}\", uo.id),\n// after\nNone => {\n    log::warn!(\"missing persistence type for order update {}, defaulting to Gtc\", uo.id);\n    Ok(TimeInForce::Gtc)\n}","handlingStrategy":"fallback","validationCode":"if uo.order_type == Limit && uo.persistence_type.is_none() {\n    log::warn!(\"order {} update missing persistence; snapshot may be stale\", uo.id);\n}","typeGuard":"fn has_persistence(uo: &UnmatchedOrder) -> bool {\n    matches!(uo.order_type, StreamingOrderType::Limit) && uo.persistence_type.is_some()\n}","tryCatchPattern":"match parse_order_status_report(&uo) {\n    Err(e) if e.to_string().contains(\"missing persistence type\") => {\n        log::warn!(\"resubscribing to get a full order image\");\n        resubscribe_orders();\n    }\n    other => other,\n}","preventionTips":["Reconnect with a fresh snapshot rather than resuming a conflated stream after gaps.","Avoid long conflation windows on order streams if you rely on full order attributes.","Track sequence/sequenceLag so you know when updates arrive without their base image."],"tags":["betfair","streaming","order-management","parsing","rust"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}