{"record":{"id":"55d08fe0130a494f","repo":"nautechsystems/nautilus_trader","slug":"synthetic-synthetic-id-already-exists","errorCode":null,"errorMessage":"`synthetic` {synthetic.id} already exists","messagePattern":"`synthetic` (.+?) already exists","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/common/src/actor/data_actor.rs","lineNumber":4309,"sourceCode":"        );\n        let data = CustomData::new(Arc::new(signal), data_type);\n        let topic = get_custom_topic(&data.data_type);\n        msgbus::publish_any(topic, &data);\n    }\n\n    /// Adds the `synthetic` instrument to the cache.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if a synthetic with the same ID already exists, or if the\n    /// backing cache fails to persist it. Panics if the actor is not registered\n    /// with a trader. // panics-doc-ok\n    pub fn add_synthetic(&self, synthetic: SyntheticInstrument) -> anyhow::Result<()> {\n        self.check_registered();\n\n        let cache = self.cache_rc();\n        if cache.borrow().synthetic(&synthetic.id).is_some() {\n            anyhow::bail!(\"`synthetic` {} already exists\", synthetic.id);\n        }\n        cache.borrow_mut().add_synthetic(synthetic)\n    }\n\n    /// Updates the `synthetic` instrument in the cache, replacing the existing entry.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if no synthetic with the same ID already exists, or if the\n    /// backing cache fails to persist the replacement. Panics if the actor is not\n    /// registered with a trader. // panics-doc-ok\n    pub fn update_synthetic(&self, synthetic: SyntheticInstrument) -> anyhow::Result<()> {\n        self.check_registered();\n\n        let cache = self.cache_rc();\n        if cache.borrow().synthetic(&synthetic.id).is_none() {\n            anyhow::bail!(\"`synthetic` {} does not exist\", synthetic.id);\n        }","sourceCodeStart":4291,"sourceCodeEnd":4327,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/actor/data_actor.rs#L4291-L4327","documentation":"`DataActor::add_synthetic` checks the cache for an existing instrument with the same `synthetic.id` before adding. Because synthetic IDs are unique keys, adding a duplicate is rejected with this bail instead of silently overwriting the cached instrument.","triggerScenarios":"Calling `actor.add_synthetic(synthetic)` when `cache.synthetic(&synthetic.id)` already returns Some — i.e. the same synthetic ID was already added (by this actor or another component).","commonSituations":"Re-running a strategy setup that adds synthetics on each start; constructing a synthetic from config where IDs collide across runs; two actors adding the same synthetic definition.","solutions":["Check `cache.synthetic(&id)` (or the actor's existing-synthetic state) before adding and skip if present","Use `update_synthetic` if the intent is to replace the definition","Generate a unique ID (e.g. include a run/venue suffix) when creating new synthetics"],"exampleFix":"// before\nactor.add_synthetic(spread)?;\n// after\nif actor.cache_rc().borrow().synthetic(&spread.id).is_none() {\n    actor.add_synthetic(spread)?;\n}","handlingStrategy":"validation","validationCode":"if cache.borrow().synthetic(&id).is_some() { /* skip add or update instead */ }","typeGuard":null,"tryCatchPattern":"match actor.add_synthetic(synthetic) {\n    Err(e) if e.to_string().contains(\"already exists\") => { /* already added; reuse existing */ }\n    other => other?,\n}","preventionTips":["Check cache before adding synthetics","Generate unique synthetic IDs per run/definition","Prefer update_synthetic when replacing an existing definition"],"tags":["cache","duplicate","synthetic"],"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-14T00:17:10.932Z"}