Summary
Calling the Tauri mdns_advertise command (e.g. via node.advertise(...) in the Tauri adapter) aborts the host process with:
thread 'main' panicked at iroh-mdns-address-lookup-0.4.0/src/lib.rs:278:
there is no reactor running, must be called from the context of a Tokio 1.x runtime
Evidence
The desktop mdns_advertise command in packages/iroh-http-tauri/src/commands.rs is declared synchronous (pub fn):
#[command]
#[cfg(all(feature = "discovery", not(mobile)))]
pub fn mdns_advertise(endpoint_handle: u64, service_name: String) -> Result<u64, String> {
...
let session = iroh_http_discovery::start_advertise(ep.raw(), &service_name)?;
...
}
Tauri runs synchronous commands on a plain worker thread with no Tokio runtime entered. start_advertise → MdnsAddressLookup::build() internally calls tokio::runtime::Handle::current(), which panics when there is no reactor in the thread-local context.
By contrast, mdns_browse is pub async fn, so Tauri runs it on the async (Tokio) runtime where the reactor is available — which is why browse works and advertise crashes.
Impact
- mDNS advertising is unusable from the Tauri plugin in v0.5.1.
- It is a hard panic, not a recoverable error, so it aborts the host application.
Root cause / precedent
This is the same bug class the Node adapter already fixed in #243: a synchronous binding called the mDNS constructor outside a runtime context. The fix there was to declare mdns_advertise async so napi runs it inside the global Tokio runtime. The Tauri adapter was never converted and retained the sync signature.
CI missed it because Rust tests run inside #[tokio::test] (a reactor is always present), whereas the real Tauri sync command runs without one — the same "test environment provides context production lacks" pattern as the ACL bug (#246).
Note: the Deno adapter is not affected — its entire dispatch runs via rt.block_on(dispatch::dispatch(...)), so even its "sync" mdnsAdvertise arm executes inside the runtime context.
Remediation
Make the desktop mdns_advertise command async fn so Tauri executes it on the async (Tokio) runtime, matching mdns_browse and the Node adapter precedent (#243). JS contract is unchanged (invoke already returns a Promise).
Acceptance criteria
Summary
Calling the Tauri
mdns_advertisecommand (e.g. vianode.advertise(...)in the Tauri adapter) aborts the host process with:Evidence
The desktop
mdns_advertisecommand inpackages/iroh-http-tauri/src/commands.rsis declared synchronous (pub fn):Tauri runs synchronous commands on a plain worker thread with no Tokio runtime entered.
start_advertise→MdnsAddressLookup::build()internally callstokio::runtime::Handle::current(), which panics when there is no reactor in the thread-local context.By contrast,
mdns_browseispub async fn, so Tauri runs it on the async (Tokio) runtime where the reactor is available — which is why browse works and advertise crashes.Impact
Root cause / precedent
This is the same bug class the Node adapter already fixed in #243: a synchronous binding called the mDNS constructor outside a runtime context. The fix there was to declare
mdns_advertiseasyncso napi runs it inside the global Tokio runtime. The Tauri adapter was never converted and retained the sync signature.CI missed it because Rust tests run inside
#[tokio::test](a reactor is always present), whereas the real Tauri sync command runs without one — the same "test environment provides context production lacks" pattern as the ACL bug (#246).Note: the Deno adapter is not affected — its entire dispatch runs via
rt.block_on(dispatch::dispatch(...)), so even its "sync"mdnsAdvertisearm executes inside the runtime context.Remediation
Make the desktop
mdns_advertisecommandasync fnso Tauri executes it on the async (Tokio) runtime, matchingmdns_browseand the Node adapter precedent (#243). JS contract is unchanged (invokealready returns aPromise).Acceptance criteria
mdns_advertise(desktop, discovery feature) runs within a Tokio runtime context.cargo clippy -- -D warningsclean for the plugin.