iced-rs/iced · error
Editor cannot have multiple strong references
Error message
Editor cannot have multiple strong references
What it means
`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.
Source
Thrown at graphics/src/text/editor.rs:67
Weak {
raw: Arc::downgrade(editor),
bounds: editor.bounds,
}
}
fn internal(&self) -> &Arc<Internal> {
self.0
.as_ref()
.expect("Editor should always be initialized")
}
fn with_internal_mut<T>(&mut self, f: impl FnOnce(&mut Internal) -> T) -> T {
let editor = self.0.take().expect("Editor should always be initialized");
// TODO: Handle multiple strong references somehow
let mut internal =
Arc::try_unwrap(editor).expect("Editor cannot have multiple strong references");
// Clear cursor cache
let _ = internal
.selection
.write()
.expect("Write to cursor cache")
.take();
let result = f(&mut internal);
self.0 = Some(Arc::new(internal));
result
}
}
impl editor::Editor for Editor {
type Font = Font;View on GitHub (pinned to 2cffa99b39)
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
Example fix
// before
let editor = weak.upgrade().expect("editor alive");
self.cached_editor = Some(editor); // strong handle kept alive across updates
self.editor.perform(action); // panics: try_unwrap sees 2 strong refs
// after
{
let editor = weak.upgrade().expect("editor alive");
draw(editor.buffer());
} // strong handle dropped here
self.editor.perform(action); // ok: single strong reference again Defensive patterns
Strategy: validation
Validate before calling
// Rule: Editor handles obtained from Weak::upgrade() must be borrow-scoped.
// Draw with it, then let it drop BEFORE any &mut Editor call:
{
let editor = weak.upgrade().expect("editor alive");
draw(editor.buffer());
} // strong handle dropped here — mutation below sees a single Arc reference
editor.perform(action); Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Editor should always be initialized
- Write to font system
- Read from font system
- Write font system
- not implemented
AI-assisted analysis of iced-rs/iced@2cffa99b39 (2026-08-16).
Data as JSON: /api/errors/c733a0d879f62f42.
Report an issue: GitHub.