helix-editor/helix · error · anyhow::Error
invalid language id: {}
Error message
invalid language id: {} What it means
Document::set_language_by_language_id looks the name up via Loader::language_for_name, which searches the languages loaded from languages.toml (and user overrides). An id that matches no configured language returns None and the method fails with "invalid language id: {id}". Note this resolves by language name, not file extension or scope.
Source
Thrown at helix-view/src/document.rs:1389
// been logged by `LanguageData::syntax_config`.
if err != syntax::HighlighterError::NoRootConfig {
log::warn!("Error building syntax for '{}': {err}", self.display_name());
}
})
.ok()
});
}
/// Set the programming language for the file if you know the language but don't have the
/// [`syntax::config::LanguageConfiguration`] for it.
pub fn set_language_by_language_id(
&mut self,
language_id: &str,
loader: &syntax::Loader,
) -> anyhow::Result<()> {
let language = loader
.language_for_name(language_id)
.ok_or_else(|| anyhow!("invalid language id: {}", language_id))?;
let config = loader.language(language).config().clone();
self.set_language(Some(config), loader);
Ok(())
}
/// Select text within the [`Document`].
pub fn set_selection(&mut self, view_id: ViewId, selection: Selection) {
// TODO: use a transaction?
self.selections
.insert(view_id, selection.ensure_invariants(self.text().slice(..)));
helix_event::dispatch(SelectionDidChange {
doc: self,
view: view_id,
})
}
/// Find the origin selection of the text in a document, i.e. where
/// a single cursor would go if it were on the first grapheme. IfView on GitHub (pinned to 079a789e8c)
Solutions
- Use the exact language name from languages.toml, e.g. :set-language-id typescript rather than "ts" or "TSX".
- If it is a custom language, verify the languages.toml/user-languages.toml entry parses (run :config-reload or check :log-open for TOML errors).
- For API callers, check loader.language_for_name(id).is_some() before calling set_language_by_language_id and surface the list of valid names.
Example fix
// before
doc.set_language_by_language_id("ts", loader)?; // Err: invalid language id: ts
// after
doc.set_language_by_language_id("typescript", loader)?; Defensive patterns
Strategy: validation
Validate before calling
let known = loader.language_for_name(language_id).is_some();
if !known {
return Err(anyhow!(
"language '{language_id}' not in languages.toml; known: e.g. rust, typescript, python"
));
}
doc.set_language_by_language_id(language_id, loader)?; Type guard
fn known_language<'a>(loader: &'a syntax::Loader, id: &str) -> Option<&'a helix_core::syntax::Language> {
loader.language_for_name(id)
} Try / catch
match doc.set_language_by_language_id(id, loader) {
Ok(()) => {}
Err(err) if err.to_string().starts_with("invalid language id") => {
// fall back to leaving the current language, tell the user which names exist
editor.set_error(format!("{err}; check names in languages.toml"));
}
Err(err) => return Err(err),
} Prevention
- Check loader.language_for_name(id) before setting.
- Source language ids from the same languages.toml that the loader was built from, never hardcode.
- After config edits, reload and confirm custom languages actually registered.
When it happens
Trigger: Calling :set-language-id with a name absent from languages.toml; an LSP integration passing a languageId string that does not match a configured language name; a custom language defined in user config that failed to load due to a TOML error, so the name never registered.
Common situations: Typos or wrong casing when switching languages manually; upstream languages.toml renames in newer Helix versions; expecting a file-type extension ("rs", "ts") to work where the language name ("rust", "typescript") is required; user-languages.toml syntax errors silently removing custom entries.
Related errors
- Command not provided
- Incorrect transport {}
- Language server '{name}' not defined
- 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/6e8d9c514374e806.
Report an issue: GitHub.