helix-editor/helix · error · StartupError
Language server '{name}' not defined
Error message
Language server '{name}' not defined What it means
During language-server startup, Registry::start_client looks up the requested server name in the syntax loader's language_server_configs (the [language-server.<name>] tables merged from languages.toml and user config). If no table with that exact name exists, this error is returned and the server never starts.
Source
Thrown at helix-lsp/src/lib.rs:632
instances.retain(|ls| id != ls.id());
if instances.is_empty() {
self.inner_by_name.remove(client.name());
}
}
fn start_client(
&mut self,
name: String,
ls_config: &LanguageConfiguration,
doc_path: Option<&std::path::Path>,
root_dirs: &[PathBuf],
enable_snippets: bool,
) -> Result<Arc<Client>, StartupError> {
let syn_loader = self.syn_loader.load();
let config = syn_loader
.language_server_configs()
.get(&name)
.ok_or_else(|| anyhow::anyhow!("Language server '{name}' not defined"))?;
let id = self.inner.try_insert_with_key(|id| {
start_client(
id,
name,
ls_config,
config,
doc_path,
root_dirs,
enable_snippets,
)
.map(|client| {
self.incoming.push(UnboundedReceiverStream::new(client.1));
client.0
})
})?;
Ok(self.inner[id].clone())
}
View on GitHub (pinned to 079a789e8c)
Solutions
- Check 'hx --health <lang>' - it shows which language servers are configured/available and surfaces this mismatch
- Add the missing definition block: [language-server.foo] with command = "..." in languages.toml (user or workspace), or fix the name to match an existing block exactly (case-sensitive)
- If you overrode the language's table in user config, re-add the [language-server.<name>] blocks the default languages.toml shipped for it
Example fix
# before - reference without definition
[language-server.myls]
# (missing)
[[language]]
name = "mylang"
language-server = [{ name = "myls" }]
# after
[language-server.myls]
command = "mylang-server"
args = ["--stdio"]
[[language]]
name = "mylang"
language-server = [{ name = "myls" }] Defensive patterns
Strategy: validation
Validate before calling
// Validate language-server references against definitions before startup:
fn ls_refs_defined(lang: &LanguageConfiguration, defs: &HashSet<String>) -> Result<(), String> {
for ls in &lang.language_server {
if !defs.contains(&ls.name) {
return Err(format!("language server '{}' not defined", ls.name));
}
}
Ok(())
} Type guard
fn is_defined_ls(name: &str, syn_loader: &helix_core::syntax::Loader) -> bool {
syn_loader.language_server_configs().contains_key(name)
} Prevention
- Run 'hx --health <lang>' after changing languages.toml - it flags undefined servers
- When overriding a language table, copy the matching [language-server.*] blocks too
- Keep names case-sensitive and identical between reference and definition
- Prefer adding new [language-server.x] blocks over editing built-in ones
When it happens
Trigger: A language's language-server = [{ name = "foo" }] (or the legacy language-server = ["foo"] list) references a name that has no [language-server.foo] section anywhere - typo, wrong case, or a server defined only in another config layer that got shadowed/removed by user languages.toml merging.
Common situations: User adds a language override in ~/.config/helix/languages.toml that replaces the default language table (array of tables semantics) and forgets to carry over the [language-server.x] definition; renaming a server block but not its reference; disabling a built-in definition while still referencing it; name casing ('vscode-html-language-server' vs 'vscode-html-language-server-removed').
Related errors
- Failed to parse snippet. Remaining input: {}
- Command not provided
- Incorrect transport {}
- Failed to load config: {}
- --config must specify a path to read
AI-assisted analysis of helix-editor/helix@079a789e8c (2026-08-16).
Data as JSON: /api/errors/01a111603538da47.
Report an issue: GitHub.