nautechsystems/nautilus_trader · error

Invalid `external_order_claims` type: {e}

Error message

Invalid `external_order_claims` type: {e}

What it means

The external_order_claims Python attribute could not be extracted either as Vec<InstrumentId> or as Vec<String>: its elements are of some other type (int, dict, mixed list, None).

Source

Thrown at crates/live/src/python/node.rs:1844

fn extract_external_order_claims_config_attr(
    config_obj: &Bound<'_, PyAny>,
) -> anyhow::Result<Option<Vec<InstrumentId>>> {
    let Ok(claims) = config_obj.getattr("external_order_claims") else {
        return Ok(None);
    };

    if claims.is_none() {
        return Ok(None);
    }

    if let Ok(claims) = claims.extract::<Vec<InstrumentId>>() {
        return Ok(Some(claims));
    }

    let claim_strings = claims
        .extract::<Vec<String>>()
        .map_err(|e| anyhow::anyhow!("Invalid `external_order_claims` type: {e}"))?;
    let claims = claim_strings
        .into_iter()
        .map(|claim| {
            InstrumentId::from_str(&claim).map_err(|e| {
                anyhow::anyhow!("Invalid `external_order_claims` instrument ID {claim}: {e}")
            })
        })
        .collect::<anyhow::Result<Vec<_>>>()?;

    Ok(Some(claims))
}

#[cfg(feature = "examples")]
type BuiltinActorRegister = for<'py> fn(&mut LiveNode, &Bound<'py, PyAny>) -> PyResult<()>;

#[cfg(feature = "examples")]
type BuiltinStrategyRegister = for<'py> fn(&mut LiveNode, &Bound<'py, PyAny>) -> PyResult<()>;

View on GitHub (pinned to d1527c24af)

Solutions

  1. Make it a list: external_order_claims = ["BTCUSDT-PERP.BINANCE"]
  2. Ensure every element is a string or an InstrumentId instance, not mixed types
  3. Do not pass None; omit the attribute to use the default

Example fix

# before
external_order_claims = "BTCUSDT-PERP.BINANCE"

# after
external_order_claims = ["BTCUSDT-PERP.BINANCE"]
Defensive patterns

Strategy: type-guard

Validate before calling

# Python
claims = cfg.get("external_order_claims")
assert claims is None or (isinstance(claims, list) and all(isinstance(c, (str, InstrumentId)) for c in claims))

Type guard

# Python
def valid_claims(c) -> bool:
    return c is None or (isinstance(c, list) and all(isinstance(x, (str, InstrumentId)) for x in c))

Try / catch

try:
    node = build_node(config)
except Exception as e:
    if "external_order_claims" in str(e) and "type" in str(e):
        # normalize to list of strings and retry

Prevention

When it happens

Trigger: Setting external_order_claims to a non-list or a list of objects that are neither InstrumentId instances nor strings, e.g. [12345] or "BTCUSDT-PERP" (a bare string, not a list).

Common situations: Passing a single instrument ID string instead of a list, or passing raw numeric venue IDs.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@d1527c24af (2026-08-27). Data as JSON: /api/errors/61043984aac2049c. Report an issue: GitHub.