nautechsystems/nautilus_trader · error · anyhow::Error

Failed to set attribute {key}: {setattr_err}

Error message

Failed to set attribute {key}: {setattr_err}

What it means

When the config class cannot be constructed via kwargs, create_config_instance falls back to building a default instance and setting each config key via setattr. If Python's setattr fails for any key (e.g. the dataclass field does not exist, or a __setattr__/__set_name__ check rejects the value), the error wraps the original Python exception message.

Source

Thrown at crates/backtest/src/python/node.rs:549

    log::debug!("Created config dict: {py_dict:?}");

    // Try kwargs first, then default constructor with setattr
    let config_instance = match config_class.call((), Some(&py_dict)) {
        Ok(instance) => {
            log::debug!("Created config instance with kwargs");
            instance
        }
        Err(kwargs_err) => {
            log::debug!("Failed to create config with kwargs: {kwargs_err}");

            match config_class.call0() {
                Ok(instance) => {
                    log::debug!("Created default config instance, setting attributes");
                    for (key, value) in config {
                        let py_value = config_value_to_py(py, key, value)?;

                        if let Err(setattr_err) = instance.setattr(key, py_value) {
                            anyhow::bail!("Failed to set attribute {key}: {setattr_err}");
                        }
                    }

                    // Only call __post_init__ if it exists (setattr path
                    // needs it, kwargs path already triggered it via __init__)
                    if instance.hasattr("__post_init__")? {
                        instance.call_method0("__post_init__")?;
                    }

                    instance
                }
                Err(default_err) => {
                    anyhow::bail!(
                        "Failed to create config instance. \
                         Tried kwargs: {kwargs_err}, default: {default_err}"
                    );
                }
            }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Compare config keys against the config class fields and remove/rename unknown keys
  2. Check the wrapped setattr_err message to find the exact failing attribute and its rejection reason
  3. Construct the config directly in Python with correct kwargs instead of relying on the default-instance fallback
  4. After upgrading NautilusTrader, diff your config keys against the new config class definitions

Example fix

// before
config = {"bar_types": "1-MINUTE-LAST", "strategy_id": "S-001"}  # typo: bar_types
// after
config = {"bar_type": "1-MINUTE-LAST", "strategy_id": "S-001"}
Defensive patterns

Strategy: validation

Validate before calling

import dataclasses
def validate_config_keys(config_cls, config: dict):
    valid = {f.name for f in dataclasses.fields(config_cls)}
    bad = set(config) - valid
    if bad:
        raise ValueError(f"unknown config keys for {config_cls.__name__}: {sorted(bad)}")

Try / catch

try:
    instance = create_config_instance(config_cls, config)
except Exception as e:
    log.error("config setattr failed: %s", e)

Prevention

When it happens

Trigger: Config dict contains a key not present on the default config class; a field is frozen or has a __post_init__/property that rejects assignment; value has the wrong type for a field with runtime validation.

Common situations: Renamed or removed config fields after a NautilusTrader upgrade; passing custom keys to a stock config class; typos in config keys (e.g. 'bar_type' vs 'bartype').

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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