{"record":{"id":"c733a0d879f62f42","repo":"iced-rs/iced","slug":"editor-cannot-have-multiple-strong-references","errorCode":null,"errorMessage":"Editor cannot have multiple strong references","messagePattern":"Editor cannot have multiple strong references","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graphics/src/text/editor.rs","lineNumber":67,"sourceCode":"\n        Weak {\n            raw: Arc::downgrade(editor),\n            bounds: editor.bounds,\n        }\n    }\n\n    fn internal(&self) -> &Arc<Internal> {\n        self.0\n            .as_ref()\n            .expect(\"Editor should always be initialized\")\n    }\n\n    fn with_internal_mut<T>(&mut self, f: impl FnOnce(&mut Internal) -> T) -> T {\n        let editor = self.0.take().expect(\"Editor should always be initialized\");\n\n        // TODO: Handle multiple strong references somehow\n        let mut internal =\n            Arc::try_unwrap(editor).expect(\"Editor cannot have multiple strong references\");\n\n        // Clear cursor cache\n        let _ = internal\n            .selection\n            .write()\n            .expect(\"Write to cursor cache\")\n            .take();\n\n        let result = f(&mut internal);\n\n        self.0 = Some(Arc::new(internal));\n\n        result\n    }\n}\n\nimpl editor::Editor for Editor {\n    type Font = Font;","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/iced-rs/iced/blob/2cffa99b395d84fe469b44dccb56bbacd2f1a157/graphics/src/text/editor.rs#L49-L85","documentation":"`with_internal_mut` needs exclusive access to the editor internals, so it runs `Arc::try_unwrap(editor).expect(\"Editor cannot have multiple strong references\")`. The Editor shares `Internal` through an Arc, and `Weak::upgrade()` produces a fresh strong handle — any upgraded handle still alive during a mutation makes try_unwrap fail and panic. The TODO comment in the source acknowledges this is unhandled.","triggerScenarios":"Calling any mutating method (perform, apply, backspace, ...) while an Editor obtained from `Weak::upgrade()` is still alive — e.g. a rendering tree kept Weak handles, upgraded them for drawing, and one outlives the update pass.","commonSituations":"Custom widgets storing `Editor::downgrade()` handles and upgrading them for layout/draw, then retaining the upgraded Editor across an update; list/container code that keeps upgraded editors for reuse; debug or replay tooling holding editors while applying edits.","solutions":["Scope upgraded handles tightly: use the Editor from Weak::upgrade() and drop it before any mutation runs","Keep one authoritative Editor; treat upgrade() results as borrow-scoped, never stored","Audit for any place that keeps an upgraded Editor in a struct, cache, or collection","As a maintainer, move mutability inside Internal (e.g. RwLock) to remove the try_unwrap invariant"],"exampleFix":"// before\nlet editor = weak.upgrade().expect(\"editor alive\");\nself.cached_editor = Some(editor); // strong handle kept alive across updates\nself.editor.perform(action); // panics: try_unwrap sees 2 strong refs\n// after\n{\n    let editor = weak.upgrade().expect(\"editor alive\");\n    draw(editor.buffer());\n} // strong handle dropped here\nself.editor.perform(action); // ok: single strong reference again","handlingStrategy":"validation","validationCode":"// Rule: Editor handles obtained from Weak::upgrade() must be borrow-scoped.\n// Draw with it, then let it drop BEFORE any &mut Editor call:\n{\n    let editor = weak.upgrade().expect(\"editor alive\");\n    draw(editor.buffer());\n} // strong handle dropped here — mutation below sees a single Arc reference\neditor.perform(action);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never store an Editor returned by Weak::upgrade() in a struct, cache, or collection","Keep exactly one authoritative Editor; use Weak handles only transiently for draw/compare","Drop upgraded handles before update passes run (end of draw scope), so try_unwrap sees one strong ref","If you need shared mutable editing, restructure around a single owner plus message passing instead of cloned editors"],"tags":["rust","iced","graphics","text-editor","arc","shared-ownership","panic","invariant"],"backgroundTag":"arc-try-unwrap-failed","analyzedSha":"2cffa99b395d84fe469b44dccb56bbacd2f1a157","analyzedAt":"2026-08-16T19:41:49.083Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}