Skip to main content

Restore missing orders for lost-transmission orphan fills

POST 

/api/v1/reconciliation/backfill-missing-orders

Restores the missing Order row behind a broker fill that has none (#1348): a lost-transmission signal left the fill with orderId null and tradeId null, with no order for it to follow (#1334, #1342). This action scans two candidate shapes (scoped to the caller's accounts, optionally narrowed to one account): every non-deleted broker_fill execution with orderId null, and every stored AccountActivity FILL row with no linked order and no matching UTM execution (#1371 - a fill that never even got an order-less Execution row). For an execution-sourced candidate, the broker order id is resolved from the stored execution data or a refetch of the broker's own fill activity; for an activity-sourced candidate it is read straight from the activity's own stored data (Alpaca's FILL activities always carry it), no broker call needed. Either way, that order is then fetched from the broker (rate limited via the #1367/#1369 throttle) and restored through ingestBrokerEvents - the one write path, never a direct Order write. An execution-sourced fill is re-attached to the restored order (orderId set), moving it from the fill-level orphan queue into the order-level orphan queue, where the existing "Link this order" reconcile action attaches a trade. An activity-sourced fill has no existing Execution row to relink, so it is ingested as a brand-new one in the same batch as the order restore. This action does not itself create or choose a trade.

Some candidates duplicate an execution that already exists for the same real-world fill: an order-less execution matching one already captured under the resolved order (2026-07-07 DELL forensics: a purge SetNull-orphaned fills from a hard-deleted order, and a later sync re-ingested the order with fresh fill rows under different broker activity ids), or an activity whose fill is already captured under some Execution row anywhere in the account (matched via the shared fill-identity rule). Both classify as duplicate_of_existing, reported with the trade the surviving execution is linked to. They are never written to or deleted; the operator reviews and resolves them as a deliberate follow-up.

TradeStation is excluded by construction: its synthesised fills carry source broker_order_synth (never broker_fill) and always have an orderId set at creation, so they never match the execution-sourced scan; it also has no per-fill activity feed, so it never writes an AccountActivity FILL row and never matches the activity-sourced scan.

Defaults to a dry run, which resolves and reports without writing. A live run (dryRun false) restores each resolvable order, re-attaches or ingests its fills, and writes one AuditLog row per restored order (action "reconciliation.backfill_missing_order", entityType "Order") plus one summary row for the run. Backs the "Backfill missing orders" action on the reconcile Broker data tab. The CLI script (apps/api/src/scripts/backfill-missing-orders.ts) is a break-glass wrapper over the same service function.

Request​

Responses​

Resolution report (dry run) or restore result (live run)