nautechsystems/nautilus_trader · error · anyhow::Error

Invalid IBOrderTags payload: expected a JSON object

Error message

Invalid IBOrderTags payload: expected a JSON object

What it means

IBOrderTags payloads are expected to be a JSON object (map of IB order field names to values). apply_ib_order_tag_json parses the provided serde_json::Value and bails if it is not a JSON object (e.g. an array, string, or number).

Source

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

    for tag in tags {
        let tag_str = tag.as_str();
        if !tag_str.starts_with("IBOrderTags:") {
            continue;
        }

        let json_str = tag_str.trim_start_matches("IBOrderTags:");
        let tags_obj = serde_json::from_str::<Value>(json_str)
            .with_context(|| format!("Invalid IBOrderTags JSON: {json_str}"))?;
        apply_ib_order_tag_json(ib_order, &tags_obj)?;
    }

    Ok(())
}

fn apply_ib_order_tag_json(ib_order: &mut IBOrder, tags_obj: &Value) -> anyhow::Result<()> {
    let Some(tags_map) = tags_obj.as_object() else {
        anyhow::bail!("Invalid IBOrderTags payload: expected a JSON object");
    };

    let mut updated_order = ib_order.clone();
    apply_ib_order_tag_overlay(&mut updated_order, tags_map)?;
    apply_ib_order_conditions(&mut updated_order, tags_obj)?;

    *ib_order = updated_order;
    Ok(())
}

fn apply_ib_order_tag_overlay(
    ib_order: &mut IBOrder,
    tags_map: &Map<String, Value>,
) -> anyhow::Result<()> {
    let mut order_value = serde_json::to_value(&*ib_order)
        .context("Failed to serialize IB order before applying IBOrderTags")?;

    for (key, value) in tags_map {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Wrap the tags in a JSON object: '{"outside_rth": true}' rather than 'outside_rth' or '[...]' Validate the payload shape before calling: serde_json::from_str::<serde_json::Map<String, Value>>() and fail fast on error Check where the tags string originates (config file, env var) and fix the encoding there

Example fix

// before
let tags = "[\"outside_rth\"]";
// after
let tags = "{\"outside_rth\": true}";
Defensive patterns

Strategy: validation

Validate before calling

let v: serde_json::Value = serde_json::from_str(&tags_str)?;
if !v.is_object() {
    return Err(anyhow::anyhow!("IBOrderTags must be a JSON object"));
}

Type guard

fn is_tags_object(v: &serde_json::Value) -> bool { v.is_object() }

Prevention

When it happens

Trigger: Calling apply_ib_order_tags with a tags payload that parses to a non-object JSON Value, such as '["outside_rth"]', '"outside_rth"', or 'null', instead of '{"outside_rth": true}'.

Common situations: Order tags passed as a JSON array of strings, a bare string from config, or a YAML/JSON scalar misread as tags; also when the tags string decodes to null.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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