Why do I get the error "there is no reactor running, must be called from the context of Tokio runtime" even though I have #[tokio::main]?
Asked Answered
T

5

42

I'm following the mdns Rust documentation and pasted the example code but it throws the following error:

thread 'main' panicked at 'there is no reactor running, must be called from the context of Tokio runtime'

Here's the code that I have:

use futures_util::{pin_mut, stream::StreamExt};
use mdns::{Error, Record, RecordKind};
use std::{net::IpAddr, time::Duration};

const SERVICE_NAME: &'static str = "_googlecast._tcp.local";

#[tokio::main]
async fn main() -> Result<(), Error> {
    // Iterate through responses from each Cast device, asking for new devices every 15s
    let stream = mdns::discover::all(SERVICE_NAME, Duration::from_secs(15))?.listen();
    pin_mut!(stream);

    while let Some(Ok(response)) = stream.next().await {
        let addr = response.records().filter_map(self::to_ip_addr).next();

        if let Some(addr) = addr {
            println!("found cast device at {}", addr);
        } else {
            println!("cast device does not advertise address");
        }
    }

    Ok(())
}

fn to_ip_addr(record: &Record) -> Option<IpAddr> {
    match record.kind {
        RecordKind::A(addr) => Some(addr.into()),
        RecordKind::AAAA(addr) => Some(addr.into()),
        _ => None,
    }
}

Dependencies:

[dependencies]
mdns = "1.1.0"
futures-util = "0.3.8"
tokio = { version = "0.3.3", features = ["full"] }

What am I missing? I tried looking online but haven't found how to create a reactor for this use case.

Toboggan answered 11/11, 2020 at 3:8 Comment(0)
I
31

You are using a newer version of Tokio, such as 0.3 or 1.x, and many packages, including mdns 1.1.0, rely on an older version of Tokio, such as 0.2.

% cargo tree -d
tokio v0.2.22
└── mdns v1.1.0
    └── example_project v0.1.0

tokio v0.3.3
└── example_project v0.1.0

For now, you will need to match versions of the Tokio runtime. The easiest way is to use Tokio 0.2 yourself. The tokio-compat-02 crate may also be useful in some cases.

See also:


Various error messages with the same root cause:

there is no reactor running, must be called from the context of a Tokio 1.x runtime

there is no reactor running, must be called from the context of Tokio runtime

not currently running on the Tokio runtime

Ism answered 11/11, 2020 at 3:20 Comment(0)
I
15

Fix for me was adding this to Cargo.toml:

[dependencies]
async-std = { version = "1", features = ["attributes", "tokio1"] }

https://github.com/ATiltedTree/ytextract/issues/25

Illinois answered 15/7, 2021 at 21:59 Comment(2)
related to : #71117002Sammons
Thank you so much! It took me 2 days to find the solution.Tease
C
9

At the time of writing, a fair amount of crates are already using Tokio v1, but others might still be under an experimental phase. Check your crates for prerelease versions which might have already upgraded their tokio runtime compatibility.

A relevant example of this was actix-web, which uses runtime 1.0 of Tokio since version 4. Although there were prereleases of this major increment since 2022-01-07, version 4.0.0 was only released in 2022-02-25.

actix-web = { version = "4.0.0-beta.10" }
Chapa answered 12/11, 2021 at 12:7 Comment(1)
Thanks. I had this error exactly in actix-web and was about to dissappointingly downgrade my tokio to 0.2. I prefer less stable beta over too old <1 versions. :PRathe
G
2

I'm using tokio v1.34.0, adding #[tokio::main] solved the problem:

#[launch]
#[tokio::main]
async fn rocket() -> _ {
Grampositive answered 24/11, 2023 at 22:34 Comment(0)
W
-1

I ran the same code that produced the error with only changes to the dependencies.

[dependencies]
mdns = "3.0.0"
futures-util = "0.3.28"
tokio = { version = "1.32.0", features 
  = ["full"] }
    
    use futures_util::{pin_mut, 
      stream::StreamExt};
    use mdns::{Error, Record, 
      RecordKind};
    use std::{net::IpAddr, 
      time::Duration};
    
    const SERVICE_NAME: &'static str = 
      "_googlecast._tcp.local";
    
    #[tokio::main]
    async fn main() -> Result<(), 
      Error> {
        // Iterate through responses from 
        // each Cast device, asking for new 
        // devices every 15s
        let stream = 
          mdns::discover::all(SERVICE_NAME, 
          Duration::from_secs(15))?.listen();
        pin_mut!(stream);
    
        while let Some(Ok(response)) = 
          stream.next().await 
        {
            let addr = 
            response.records().filter_map(  
              self::to_ip_addr).next();
    
            if let Some(addr) = addr {
                println!("found cast device 
                  at {}", addr);
            } else {
                println!("cast device does 
                  not advertise address");
            }
        }
    
        Ok(())
    }
    
    fn to_ip_addr(record: &Record) -> 
        Option<IpAddr> {
        match record.kind {
            RecordKind::A(addr) => 
              Some(addr.into()),
            RecordKind::AAAA(addr) => 
              Some(addr.into()),
            _ => None,
        }
    }

// A small sample of the output I 
// received without error is below:

found cast device at 10.0.0.165
found cast device at 10.0.0.171
found cast device at 10.0.0.158
Wolford answered 10/9, 2023 at 13:9 Comment(3)
This answer needs to provide more supporting information and something new/unique that the other answers don't provide.Lishalishe
The following code is the same as the person receiving the following error:Wolford
I added more substance to my original submittal. Hope this helps.Wolford

© 2022 - 2024 — McMap. All rights reserved.