How do I solve the error "thread 'main' panicked at 'no current reactor'"?
Asked Answered
P

1

7

I am trying to connect to a database:

extern crate tokio; // 0.2.6, features = ["full"]
extern crate tokio_postgres; // 0.5.1

use futures::executor;
use tokio_postgres::NoTls;

fn main() {
    let fut = async {
        let (client, connection) = match tokio_postgres::connect("actual stuff", NoTls).await {
            Ok((client, connection)) => (client, connection),
            Err(e) => panic!(e),
        };
        tokio::spawn(async move {
            if let Err(e) = connection.await {
                eprintln!("connection error: {}", e);
            }
        });

        let rows = match client
            .query(
                "SELECT $1 FROM planet_osm_point WHERE $1 IS NOT NULL LIMIT 100",
                &[&"name"],
            )
            .await
        {
            Ok(rows) => rows,
            Err(e) => panic!(e),
        };
        let names: &str = rows[0].get("name");
        println!("{:?}", names);
    };
    executor::block_on(fut);
    println!("Hello, world!");
}

It compiled, but when I ran it, I received the error message

thread 'main' panicked at 'no current reactor'
Plovdiv answered 3/1, 2020 at 16:56 Comment(1)
Doesn't it require the "#[tokio::main]" macro above the main function?Tephrite
K
1

When using many (but not all) Tokio features, you must use the Tokio reactor. In your code, you are trying to use the general executor provided by the futures crate (executor::block_on). Using the Tokio executor and reactor is normally done via use of the #[tokio::main] macro:

#[tokio::main]
async fn main() {
    let (client, connection) = match tokio_postgres::connect("actual stuff", NoTls).await {
        Ok((client, connection)) => (client, connection),
        Err(e) => panic!(e),
    };
    tokio::spawn(async move {
        if let Err(e) = connection.await {
            eprintln!("connection error: {}", e);
        }
    });

    let rows = match client
        .query(
            "SELECT $1 FROM planet_osm_point WHERE $1 IS NOT NULL LIMIT 100",
            &[&"name"],
        )
        .await
    {
        Ok(rows) => rows,
        Err(e) => panic!(e),
    };
    let names: &str = rows[0].get("name");
    println!("{:?}", names);
}

The very first example in the tokio_postgres docs even shows you how to do this:

#[tokio::main] // By default, tokio_postgres uses the tokio crate as its runtime.
async fn main() -> Result<(), Error> {

One reason this happens is because you are using tokio::spawn which has this documented:

Panics if called from outside of the Tokio runtime.

See also:


This doesn't print what you want:

Err(e) => panic!(e),

You want

Err(e) => panic!("{}", e),
Kierakieran answered 3/1, 2020 at 17:39 Comment(4)
what exactly does the [tokio::main] do exactly I'm confusedPlovdiv
@Plovdiv it's a macro. If you expand the macro, you can see exactly what it does: How do I see the expanded macro code that's causing my compile error?.Kierakieran
Why do I need to use Tokio reactor if I'm trying to use a feature of features and not tokio?Supplicatory
"a feature of features"? I don't know what you mean. If you meant futures, then click the link to the related question and use block_on. If you need to use tokio::main, then you (or a dependency) are using a Tokio feature.Kierakieran

© 2022 - 2024 — McMap. All rights reserved.