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

  1. Scope upgraded handles tightly: use the Editor from Weak::upgrade() and drop it before any mutation runs
  2. Keep one authoritative Editor; treat upgrade() results as borrow-scoped, never stored
  3. Audit for any place that keeps an upgraded Editor in a struct, cache, or collection
  4. 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

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


AI-assisted analysis of iced-rs/iced@2cffa99b39 (2026-08-16). Data as JSON: /api/errors/c733a0d879f62f42. Report an issue: GitHub.