nautechsystems/nautilus_trader · error · anyhow::Error

Failed to restore IB order JSON after invalid IBOrderTags fi

Error message

Failed to restore IB order JSON after invalid IBOrderTags field: {field}

What it means

When a tag value fails IBOrder deserialization, apply_order_field_update tries to restore the previous value in the JSON mirror. If that mirror is no longer an object at restore time, the original IBOrder cannot be safely restored, so it bails to avoid returning a half-mutated order.

Source

Thrown at crates/adapters/interactive_brokers/src/execution/transform/tags.rs:118

) -> anyhow::Result<()> {
    let Some(order_obj) = order_value.as_object_mut() else {
        anyhow::bail!("Failed to apply IBOrderTags because IB order JSON is not an object");
    };

    if !order_obj.contains_key(field) {
        anyhow::bail!("Unsupported IBOrderTags field: {field}");
    }

    let previous = order_obj.insert(field.to_string(), value);

    match serde_json::from_value::<IBOrder>(order_value.clone()) {
        Ok(updated_order) => {
            *ib_order = updated_order;
            Ok(())
        }
        Err(e) => {
            let Some(order_obj) = order_value.as_object_mut() else {
                anyhow::bail!(
                    "Failed to restore IB order JSON after invalid IBOrderTags field: {field}"
                );
            };

            match previous {
                Some(previous) => order_obj.insert(field.to_string(), previous),
                None => order_obj.remove(field),
            };
            Err(anyhow::anyhow!("Invalid IBOrderTags field {field}: {e}"))
        }
    }
}

fn sync_order_field(
    order_value: &mut Value,
    field: &str,
    ib_order: &IBOrder,
) -> anyhow::Result<()> {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Fix the tag value so it deserializes into IBOrder (correct type for the field) — this avoids the restore path entirely Ensure IBOrder serializes to a JSON object (no custom newtype Serialize) Clone IBOrder before applying tags and discard on failure instead of relying on the JSON-mirror restore

Example fix

// before
{"order_ref": 12345} // number where string expected
// after
{"order_ref": "my-strategy-1"}
Defensive patterns

Strategy: try-catch

Try / catch

let snapshot = ib_order.clone();
if let Err(e) = apply_ib_order_tags(&mut ib_order, &tags) {
    ib_order = snapshot; // restore independently of the adapter's internal restore
    return Err(e);
}

Prevention

When it happens

Trigger: apply_order_field_update: serde_json::from_value::<IBOrder>(order_value.clone()) fails (the inserted value has the wrong type/shape for the field), and then order_value.as_object_mut() also returns None during the restore path.

Common situations: Follows error 864's root cause: a non-object serialized IBOrder combined with a tag value that fails validation; indicates both a bad tag value and a broken internal JSON mirror.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/24cc32f77b28732b. Report an issue: GitHub.