libnyanpasu/clash-nyanpasu · error

failed to create tokio runtime

Error message

failed to create tokio runtime

What it means

listen() spawns a thread that builds a current-thread tokio runtime via Builder::build().expect(). Runtime construction can fail (e.g. when a required IO/driver feature is disabled or resources are unavailable), and the library panics instead of returning an error because it runs on a background thread.

Source

Thrown at backend/tauri-plugin-deep-link/src/windows.rs:89

static CRASH_COUNT: AtomicU16 = AtomicU16::new(0);

pub fn listen<F: FnMut(String) + Send + 'static>(mut handler: F) -> Result<()> {
    if CRASH_COUNT.load(Ordering::Acquire) > 5 {
        panic!("Local socket too many crashes");
    }

    std::thread::spawn(move || {
        let name = ID
            .get()
            .expect("listen() called before prepare()")
            .as_str()
            .to_ns_name::<GenericNamespaced>()
            .unwrap();
        tokio::runtime::Builder::new_current_thread()
            .enable_all()
            .build()
            .expect("failed to create tokio runtime")
            .block_on(async move {
                let sdsf = "D:(A;;GA;;;WD)".to_wtf_16().unwrap();
                let sd = SecurityDescriptor::deserialize(&sdsf).expect("Failed to deserialize SD");
                let listener = ListenerOptions::new()
                    .name(name)
                    .nonblocking(ListenerNonblockingMode::Both)
                    .security_descriptor(sd)
                    .create_tokio()
                    .expect("Can't create listener");

                loop {
                    match listener.accept().await {
                        Ok(conn) => {
                            let (rx, mut tx) = conn.split();
                            let mut reader = BufReader::new(rx);
                            let mut buf = String::new();
                            if let Err(e) = reader.read_line(&mut buf).await {
                                log::error!("Error reading from connection: {e}");

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Ensure the tokio dependency includes features ["rt", "net", "macros"] (or just use default features)
  2. Check for workspace dependency unification stripping tokio features (cargo tree -i tokio)
  3. If the failure persists, restructure to run the listener on an existing tokio runtime instead of building a new one

Example fix

// before
tokio = { version = "1", default-features = false }
// after
tokio = { version = "1", features = ["rt", "net", "macros"] }
Defensive patterns

Strategy: retry

Validate before calling

// ensure tokio features are enabled in Cargo.toml:
// tokio = { version = "1", features = ["rt", "net", "macros"] }
let rt = match tokio::runtime::Builder::new_current_thread().enable_all().build() {
    Ok(rt) => rt,
    Err(e) => { log::error!("tokio runtime: {e}"); return; }
};

Try / catch

let rt = tokio::runtime::Builder::new_current_thread()
    .enable_all().build()
    .expect("failed to create tokio runtime: check tokio 'rt'/'net' features");

Prevention

When it happens

Trigger: tokio built without the features this listener needs (rt, net, etc.) so enable_all()/build() fails; pathological environments where runtime creation fails (resource exhaustion).

Common situations: Dependency conflicts downgrading/disabling tokio features (e.g. another crate enabling default-features = false); minimal builds missing 'net'/'rt' features; running in heavily restricted environments.

Related errors


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/c65ddc92c260468f. Report an issue: GitHub.