{"record":{"id":"b192ce1a4b65f3ab","repo":"nautechsystems/nautilus_trader","slug":"component-component-id-is-already-registered-wit","errorCode":null,"errorMessage":"Component {component_id} is already registered with trader {}","messagePattern":"Component (.+?) is already registered with trader (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/system/src/python/registration.rs","lineNumber":476,"sourceCode":"    /// live strategy would overwrite that strategy's clock, registry entries, and wrapper, and a\n    /// rollback would then remove state the attempt did not create. The lifecycle collections are\n    /// checked alongside the clocks because a component registered externally and tracked through\n    /// `add_*_id_for_lifecycle` has no trader-owned clock.\n    fn ensure_component_id_available(&self, component_id: ComponentId) -> anyhow::Result<()> {\n        let id = component_id.inner();\n        let tracked = self.clocks.contains_key(&component_id)\n            || self.actor_ids.iter().any(|actor_id| actor_id.inner() == id)\n            || self\n                .strategy_ids\n                .iter()\n                .any(|strategy_id| strategy_id.inner() == id)\n            || self\n                .exec_algorithm_ids\n                .iter()\n                .any(|exec_algorithm_id| exec_algorithm_id.inner() == id);\n\n        if tracked {\n            anyhow::bail!(\n                \"Component {component_id} is already registered with trader {}\",\n                self.trader_id\n            );\n        }\n\n        Ok(())\n    }\n}\n\nfn create_python_actor(config: &ImportableActorConfig) -> anyhow::Result<(Py<PyAny>, ActorId)> {\n    let (module_name, class_name) = split_import_path(&config.actor_path, \"actor_path\")?;\n\n    log::info!(\"Importing actor from module: {module_name} class: {class_name}\");\n\n    Python::attach(|py| -> anyhow::Result<(Py<PyAny>, ActorId)> {\n        let actor_class = import_python_class(py, module_name, class_name)?;\n        let config_instance = create_config_instance(py, &config.config_path, &config.config)?;\n","sourceCodeStart":458,"sourceCodeEnd":494,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/system/src/python/registration.rs#L458-L494","documentation":"The generic component-ID collision guard: thrown when the ComponentId (actor, strategy, or exec algorithm) you are registering is already tracked by this trader under any of `actor_ids`, `strategy_ids`, or `exec_algorithm_ids`. It prevents cross-kind ID collisions where, say, an actor and a strategy share the same identifier, which would break component lookup and message routing.","triggerScenarios":"Calling add_python_actor_instance, prepare/commit_python_strategy_instance, or add_py/python_exec_algorithm_instance with a component whose ID equals an existing component of ANY kind on the trader (the same-kind duplicates get their own messages first; this fires for cross-kind collisions or after those checks pass).","commonSituations":"An actor named 'MyStrategy-001' colliding with a strategy ID; config files that reuse the same component name across actor/strategy/exec-algorithm sections; migrating components between kinds without renaming.","solutions":["Rename the conflicting component so each ComponentId is globally unique on the trader","Inspect `trader_id` and the existing ID sets to find the colliding component","Move the component to a different trader instance if both registrations are intentional","Consolidate duplicate config entries sharing one name"],"exampleFix":"// before\nActorConfig { name: 'Alpha' }      // actor\nStrategyConfig { name: 'Alpha' }   // strategy -> ComponentId collision\n// after\nStrategyConfig { name: 'AlphaStrategy' }","handlingStrategy":"validation","validationCode":"all_ids = trader.actor_ids() + trader.strategy_ids() + trader.exec_algorithm_ids()\nids = [c.value for c in all_ids]\nassert len(ids) == len(set(ids)), f\"duplicate component ids: {ids}\"","typeGuard":"def component_id_is_free(trader, component_id) -> bool:\n    return component_id.value not in (\n        {c.value for c in trader.actor_ids()} |\n        {c.value for c in trader.strategy_ids()} |\n        {c.value for c in trader.exec_algorithm_ids()}\n    )","tryCatchPattern":"try:\n    trader.add_actor(actor)\nexcept ValueError as e:\n    if \"already registered with trader\" in str(e):\n        raise ConfigError(f\"component name collision: {e}\") from e\n    else:\n        raise","preventionTips":["Namespace component names by kind (e.g. 'AlphaActor', 'AlphaStrategy')","Lint configs for duplicate names across all component sections before launch","One trader per logically isolated component set"],"tags":["rust","registration","duplicate-id","component"],"backgroundTag":"file-already-exists","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}