{"record":{"id":"2edcbafb4b82ea74","repo":"RightNow-AI/openfang","slug":"failed-to-create-tokio-runtime","errorCode":null,"errorMessage":"Failed to create Tokio runtime","messagePattern":"Failed to create Tokio runtime","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openfang-cli/src/mcp.rs","lineNumber":155,"sourceCode":"fn create_backend(config: Option<std::path::PathBuf>) -> McpBackend {\n    // Try daemon first\n    if let Some(base_url) = super::find_daemon() {\n        let client = reqwest::blocking::Client::builder()\n            .timeout(std::time::Duration::from_secs(120))\n            .build()\n            .expect(\"Failed to build HTTP client\");\n        return McpBackend::Daemon { base_url, client };\n    }\n\n    // Fall back to in-process kernel\n    let kernel = match OpenFangKernel::boot(config.as_deref()) {\n        Ok(k) => k,\n        Err(e) => {\n            eprintln!(\"Failed to boot kernel for MCP: {e}\");\n            std::process::exit(1);\n        }\n    };\n    let rt = tokio::runtime::Runtime::new().expect(\"Failed to create Tokio runtime\");\n    McpBackend::InProcess {\n        kernel: Box::new(kernel),\n        rt,\n    }\n}\n\n/// Read a Content-Length framed JSON-RPC message from the reader.\nfn read_message(reader: &mut impl BufRead) -> io::Result<Option<Value>> {\n    // Read headers until empty line\n    let mut content_length: usize = 0;\n    loop {\n        let mut header = String::new();\n        let bytes_read = reader.read_line(&mut header)?;\n        if bytes_read == 0 {\n            return Ok(None); // EOF\n        }\n\n        let trimmed = header.trim();","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/RightNow-AI/openfang/blob/acf2587e46be174c10200489c9a2d23a39a98aeb/crates/openfang-cli/src/mcp.rs#L137-L173","documentation":"tokio::runtime::Runtime::new() fails when the runtime cannot build its I/O or time drivers — commonly inside a process that already has a Tokio runtime context, or when OS resources (epoll/eventfd, threads) are unavailable. create_backend() panics via expect, killing the MCP process when falling back to in-process kernel mode.","triggerScenarios":"Runtime::new() called from create_backend() when not running inside an async context but the OS cannot provide reactor resources, or when called from code already inside another Tokio runtime (nested runtime creation is allowed for Runtime::new but worker/thread spawn failures raise errors), typically under thread/fd exhaustion.","commonSituations":"MCP server spawned by another async tooling host under low ulimit -u (thread limits) or fd limits; linking tokio features mismatched (no 'rt-multi-thread' or io driver features) causing driver init failure.","solutions":["Check ulimit -n / ulimit -u and raise fd/thread limits in constrained environments.","Enable required tokio features (rt-multi-thread, net, time) in Cargo.toml.","Build the runtime once at process start (lazy static / OnceLock) instead of inside create_backend to avoid repeated creation.","Propagate the error and exit with a clear message rather than a panic string.","Verify no tokio::test/#[tokio::main] wrapper already created a runtime around this code path."],"exampleFix":"// before\nlet rt = tokio::runtime::Runtime::new().expect(\"Failed to create Tokio runtime\");\n// after\nlet rt = tokio::runtime::Runtime::new().unwrap_or_else(|e| {\n    eprintln!(\"cannot start Tokio runtime: {e}\");\n    std::process::exit(1);\n});","handlingStrategy":"try-catch","validationCode":"// Verify resource headroom before creating a runtime\nfn runtime_env_ok() -> bool {\n    // cheap proxy: can we spawn a thread?\n    std::thread::Builder::new().stack_size(64 * 1024).spawn(|| {}).map(|h| h.join().is_ok()).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"// handle Result instead of expect\nlet rt = match tokio::runtime::Runtime::new() {\n    Ok(rt) => rt,\n    Err(e) => {\n        eprintln!(\"Failed to create Tokio runtime: {e}\");\n        std::process::exit(1);\n    }\n};","preventionTips":["Create the runtime once per process (OnceLock), not per backend construction.","Check ulimit -n/-u in constrained MCP host environments.","Enable tokio rt-multi-thread/net/time features so drivers exist.","Avoid creating blocking runtimes inside an existing async runtime context."],"tags":["tokio","runtime","mcp","panic","async"],"backgroundTag":"tokio-runtime-creation-failed","analyzedSha":"acf2587e46be174c10200489c9a2d23a39a98aeb","analyzedAt":"2026-09-02T22:42:28.464Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}