{"record":{"id":"b10a86531b2f6096","repo":"janhq/jan","slug":"failed-to-get-current-exe-path","errorCode":null,"errorMessage":"Failed to get current exe path","messagePattern":"Failed to get current exe path","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src-tauri/src/core/mcp/helpers.rs","lineNumber":404,"sourceCode":"            }\n\n            Ok(())\n        }\n        Err(e) => {\n            log::error!(\"Failed to start MCP server {name} on first attempt: {e}\");\n            Err(e)\n        }\n    }\n}\n\nasync fn schedule_mcp_start_task<R: Runtime>(\n    app: tauri::AppHandle<R>,\n    servers: SharedMcpServers,\n    name: String,\n    config: Value,\n) -> Result<(), String> {\n    let app_path = get_jan_data_folder_path(app.clone());\n    let exe_path = env::current_exe().expect(\"Failed to get current exe path\");\n    let exe_parent_path = exe_path\n        .parent()\n        .expect(\"Executable must have a parent directory\");\n    let bin_path = exe_parent_path.to_path_buf();\n\n    let config_params = extract_command_args(&config)\n        .ok_or_else(|| format!(\"Failed to extract command args from config for {name}\"))?;\n\n    if let (Some(\"http\"), Some(url)) = (\n        config_params.transport_type.as_deref(),\n        config_params.url.clone(),\n    ) {\n        let transport = StreamableHttpClientTransport::with_client(\n            reqwest::Client::builder()\n                .default_headers({\n                    // Map envs to request headers\n                    let mut headers: tauri::http::HeaderMap = reqwest::header::HeaderMap::new();\n                    for (key, value) in config_params.headers.iter() {","sourceCodeStart":386,"sourceCodeEnd":422,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/src-tauri/src/core/mcp/helpers.rs#L386-L422","documentation":"This is a panic (.expect) from env::current_exe() inside schedule_mcp_start_task, which prepares to launch a stdio-based MCP server as a child process using the jan binary's directory as the working path. current_exe() fails under the same conditions as in spawn_detached: missing /proc on Linux, deleted binary inode, sandbox restrictions.","triggerScenarios":"Starting an MCP server configured with command 'npx' or a local binary while running in a container without /proc. The jan binary was replaced by an updater while MCP servers are being initialized. Running in a minimal namespace/jail that blocks procfs.","commonSituations":"AppImage or Flatpak sandboxes. Docker dev containers without procfs. Post-update first launch where the old binary path no longer exists. SELinux denying readlink on /proc/self/exe.","solutions":["Ensure /proc/self/exe is accessible in the runtime environment.","Avoid replacing the jan binary while MCP servers are being spawned.","Cache the exe path at startup rather than re-resolving it per MCP server start.","Fall back to std::env::current_dir().join(argv[0]) when current_exe fails."],"exampleFix":"// before\nlet exe_path = env::current_exe().expect(\"Failed to get current exe path\");\n\n// after\nlet exe_path = env::current_exe().unwrap_or_else(|e| {\n    log::warn!(\"current_exe() failed ({e}); using argv[0] fallback\");\n    PathBuf::from(std::env::args().next().unwrap_or_default())\n});","handlingStrategy":"fallback","validationCode":"// At startup, cache the exe path so MCP start tasks don't need current_exe\nuse std::sync::OnceLock;\n\nstatic EXE_PATH: OnceLock<PathBuf> = OnceLock::new();\n\npub fn init_exe_path() {\n    let _ = EXE_PATH.get_or_init(|| {\n        std::env::current_exe().unwrap_or_else(|e| {\n            log::warn!(\"current_exe failed at init: {e}\");\n            PathBuf::from(std::env::args().next().unwrap_or_default())\n        })\n    });\n}\n\npub fn get_cached_exe_path() -> &'static PathBuf {\n    EXE_PATH.get().expect(\"init_exe_path not called\")\n}","typeGuard":null,"tryCatchPattern":"// Replace .expect with a fallback\nlet exe_path = match env::current_exe() {\n    Ok(p) => p,\n    Err(e) => {\n        log::error!(\"current_exe() failed: {e}; MCP server spawn may fail\");\n        return Err(format!(\"Cannot resolve executable path: {e}\"));\n    }\n};","preventionTips":["Cache the exe path at app startup rather than resolving per MCP server start.","Ensure /proc is mounted in container environments.","Fall back to argv[0] resolved via PATH when current_exe fails.","Log the exe path at startup so failures are diagnosable."],"tags":["panic","current-exe","mcp","container","sandbox"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}