AprilNEA/OpenLogi · warning
client dropped before the registry resolved
Error message
client dropped before the registry resolved
What it means
Inside `watch_model`, an async callback captured only a `Weak` handle to the client entity. When the callback finally runs, `weak.upgrade()` returned `None` because the client was dropped, so the poll task cannot resolve the asset registry and bails instead of panicking. It is an expected-shutdown condition surfaced as an error rather than a crash.
Solutions
- Treat it as benign shutdown noise: filter or ignore this error in the poll task's result handling.
- Ensure the watch task is cancelled/aborted when the client is dropped so it never runs after teardown.
- If it fires during normal operation, find what drops the client early (agent disconnect, failed startup) and fix that lifecycle bug.
- Log at debug/trace level instead of propagating it as a user-visible failure.
Example fix
// before
let Some(client) = weak.upgrade() else {
anyhow::bail!("client dropped before the registry resolved");
};
// after
let Some(client) = weak.upgrade() else {
log::debug!("asset watch cancelled: client dropped before the registry resolved");
return Ok(());
}; Defensive patterns
Strategy: try-catch
Try / catch
match poll_result {
Err(e) if e.to_string().contains("client dropped before the registry resolved") => {
log::debug!("asset watch cancelled during shutdown"); // benign
}
Err(e) => log::error!("asset watch failed: {e}"),
Ok(v) => apply(v),
} Prevention
- Abort watch tasks when their owning entity is dropped (use the weak handle as a cancellation signal)
- Keep the client alive until the first registry resolution completes before closing views
- Log this condition at debug level so shutdown noise is not escalated
When it happens
Trigger: The desktop app closes a services/assets client (e.g. a view is unmounted or the app shuts down) while a spawned watch/poll task for `(ROOT, "model", ...)` is still pending; on its next tick the task upgrades the weak handle, fails, and returns this error.
Common situations: Rapid navigation away from the device-assets view before the registry resolves; quitting the app with in-flight asset queries; the agent connection being torn down, dropping the client that owned the poll task.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
AI-assisted analysis of AprilNEA/OpenLogi@e846e6f4b4 (2026-09-13).
Data as JSON: /api/errors/aec3508da0de87d1.
Report an issue: GitHub.
Appendix: source
Thrown at crates/openlogi-desktop/src/services/assets/queries.rs:102
///
/// The returned task owns the subscription. Dropping it unsubscribes, after
/// which the entry follows normal GC.
pub(crate) fn watch_model(
client: &SwrClient,
preference: AssetSourcePreference,
target: AssetTarget,
tx: UnboundedSender<bool>,
cx: &AsyncApp,
) -> Task<()> {
let weak = client.downgrade();
let handle = client.subscribe(
(ROOT, "model", model_key(&target)),
move |_| {
let weak = weak.clone();
let target = target.clone();
async move {
let Some(client) = weak.upgrade() else {
anyhow::bail!("client dropped before the registry resolved");
};
let registry = registry(&client, preference)
.await
.map_err(|e| anyhow::anyhow!("{e}"))?;
sync_target(®istry, &target)
}
},
default_options(),
);
settled_outcomes(handle, tx, "asset sync", cx)
}
/// Watch the registry on its own, for the window before any device has appeared.
///
/// The old scheduler special-cased this ("fetch the index even with no
/// devices") so resolution works the moment a first device shows up. Once
/// devices exist their own entries depend on this one, and this subscription
/// just keeps it warm.View on GitHub (pinned to e846e6f4b4)