{"record":{"id":"f9a452def1a25521","repo":"nautechsystems/nautilus_trader","slug":"provider-gtd-order-requires-a-valid-positive-ex","errorCode":null,"errorMessage":"provider GTD order {} requires a valid positive expiration","messagePattern":"provider GTD order (.+?) requires a valid positive expiration","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/execution/reconciliation.rs","lineNumber":389,"sourceCode":"        &format!(\"provider order {} matched quantity\", order.id),\n        true,\n    )?;\n    validate_price_evidence(\n        order.price,\n        price_precision,\n        &format!(\"provider order {} price\", order.id),\n    )?;\n    let ts_accepted = order\n        .created_at\n        .checked_mul(NANOSECONDS_IN_SECOND)\n        .with_context(|| {\n            format!(\n                \"provider order {} created_at seconds {} overflow Unix nanoseconds\",\n                order.id, order.created_at,\n            )\n        })?;\n    let expire_time = parse_provider_order_expiration(order)?;\n    anyhow::ensure!(\n        TimeInForce::from(order.order_type) != TimeInForce::Gtd || expire_time.is_some(),\n        \"provider GTD order {} requires a valid positive expiration\",\n        order.id,\n    );\n    Ok(ValidatedOrderRow {\n        venue_order_id: checked_venue_order_id(&order.id, \"provider order\")?,\n        ts_accepted: UnixNanos::from(ts_accepted),\n        expire_time,\n    })\n}\n\nfn validate_trade_values(\n    quantity: Decimal,\n    price: Decimal,\n    size_precision: u8,\n    quantity_field: &str,\n    price_field: &str,\n) -> anyhow::Result<Price> {","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/execution/reconciliation.rs#L371-L407","documentation":"When rebuilding an order report from a provider PolymarketOpenOrder, GTD (Good-Till-Date) orders must carry a parsable positive expiration timestamp. parse_provider_order_expiration returns Option<UnixNanos>; if the provider GTD order has no usable expiration, this anyhow error aborts validation in validate_order_row_values.","triggerScenarios":"build_order_report_from_order processes a provider order whose order_type maps to TimeInForce::Gtd but the expiration field is missing, zero, negative, or unparseable, so expire_time is None.","commonSituations":"Provider API responses omitting the expiration for legacy GTC/GTD orders; epoch timestamp of 0 treated as no expiration; orders imported before the adapter began persisting expire_time; stale local order cache rows with null expiration columns.","solutions":["Re-fetch the order from the Polymarket API to obtain its expiration and refresh the cached provider order.","If the order is genuinely not time-limited, correct its order_type to Gtc so the GTD check does not apply.","Fix the persistence layer to store/populate expiration UnixNanos for GTD orders instead of null/0."],"exampleFix":"// before\nlet mut order = cached.clone(); // order_type: Gtd, expiration: None\nlet report = build_order_report_from_order(&provider_order, &order)?;\n// after\norder.set_time_in_force(TimeInForce::Gtd(UnixNanos::from(expire_unix_secs))); // populate before build\nlet report = build_order_report_from_order(&provider_order, &order)?;","handlingStrategy":"validation","validationCode":"fn has_valid_gtd_expiration(order: &PolymarketOpenOrder) -> bool {\n    TimeInForce::from(order.order_type) != TimeInForce::Gtd\n        || order.expiration.map(|e| e.as_u64() > 0).unwrap_or(false)\n}","typeGuard":"fn is_gtd_with_expiry(o: &PolymarketOpenOrder) -> Option<UnixNanos> {\n    if TimeInForce::from(o.order_type) == TimeInForce::Gtd { o.expiration.filter(|e| e.as_u64() > 0) } else { None }\n}","tryCatchPattern":"match build_order_report_from_order(&provider_order, &cached) {\n    Err(e) if e.to_string().contains(\"requires a valid positive expiration\") => {\n        refresh_order_from_provider(&provider_order.id).await?; // re-fetch with expiration\n    }\n    other => other?,\n}","preventionTips":["Always persist expiration UnixNanos for GTD orders in the local cache","Re-fetch provider orders instead of trusting stale cached rows for GTD","Validate TIF/expiration pairing when orders are first submitted, not only at reconciliation"],"tags":["polymarket","reconciliation","gtd","expiration"],"backgroundTag":"missing-required-argument","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"}