{"record":{"id":"09dc38d562b5b0df","repo":"helix-editor/helix","slug":"failed-to-start-debug-client","errorCode":null,"errorMessage":"Failed to start debug client: {}","messagePattern":"Failed to start debug client: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helix-term/src/commands/dap.rs","lineNumber":143,"sourceCode":"        .editor\n        .workspace_trust\n        .query(&workspace, helix_loader::workspace_trust::TrustQuery::Dap)\n        .is_trusted()\n    {\n        bail!(\"Workspace is not trusted. Run `:workspace-trust` to enable the debug adapter.\");\n    }\n\n    let doc = doc!(cx.editor);\n    let config = doc\n        .language_config()\n        .and_then(|config| config.debugger.as_ref())\n        .ok_or_else(|| anyhow!(\"No debug adapter available for language\"))?;\n\n    let id = cx\n        .editor\n        .debug_adapters\n        .start_client(socket, config)\n        .map_err(|e| anyhow!(\"Failed to start debug client: {}\", e))?;\n\n    // TODO: avoid refetching all of this... pass a config in\n    let template = match name {\n        Some(name) => config.templates.iter().find(|t| t.name == name),\n        None => config.templates.first(),\n    }\n    .ok_or_else(|| anyhow!(\"No debug config with given name\"))?;\n\n    let mut args: HashMap<&str, Value> = if let Some(params) = params.as_ref() {\n        let preprocessed_params = prepare_dap_params(template, params);\n        template\n            .args\n            .iter()\n            .map(|(k, v)| (k.as_str(), map_value(v, &preprocessed_params)))\n            .collect()\n    } else {\n        template\n            .args","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/helix-editor/helix/blob/079a789e8cb08ead67f19e1971a1b7438b37354b/helix-term/src/commands/dap.rs#L125-L161","documentation":"After resolving a debugger config, helix spawns the adapter process named by its `command` field via Editor::debug_adapters.start_client. If the executable is not found on PATH or spawning fails, the cause is wrapped as 'Failed to start debug client: <err>'. The failure happens at process creation, before any DAP handshake.","triggerScenarios":"languages.toml debugger `command = \"lldb-vscode\"` while only `lldb-dap` is installed (LLVM 17+ renamed the binary); adapter installed but not on helix's PATH (launched from a GUI); codelldb installed only as a VSCode extension.","commonSituations":"Adapter binary renames across toolchain versions; PATH differences between terminal and desktop launcher environments; adapters bundled inside other tools' directories.","solutions":["Verify helix can see the binary in its environment: `:sh which <command>` (or run `which` from the same shell/launcher).","Update `command` in the debugger config to the name that exists, or use an absolute path to the adapter binary.","Install the adapter and fully restart helix so the spawn environment is refreshed."],"exampleFix":"# before\n[language.debugger]\ncommand = \"lldb-vscode\"\n# after\n[language.debugger]\ncommand = \"/usr/bin/lldb-dap\"","handlingStrategy":"validation","validationCode":"// confirm the adapter resolves on PATH before starting a session\nif which::which(&dbg.command).is_err() {\n    // tell the user to install it / fix `command` before :debug-start\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = dap_start_impl(cx, name, addr, args) {\n    cx.editor.set_error(format!(\"debug: {e}\")); // keep editing; cause names the spawn failure\n}","preventionTips":["Pin DAP `command` values to binaries verified with `which` in helix's own environment (`:sh which ...`).","Prefer absolute paths for adapters installed outside standard PATH locations.","Re-check adapter names after toolchain upgrades (e.g. lldb-vscode -> lldb-dap)."],"tags":["dap","debugging","process-spawn","path"],"backgroundTag":null,"analyzedSha":"079a789e8cb08ead67f19e1971a1b7438b37354b","analyzedAt":"2026-08-16T09:09:59.668Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}