oraios/serena · error · ValueError
Language server for language {ls_id.value} already present
Error message
Language server for language {ls_id.value} already present What it means
add_language_server refuses duplicates: if a server for the requested language is already managed, it raises ValueError rather than replacing it. To replace a server, remove_language_server must be called first.
Source
Thrown at src/serena/ls_manager.py:211
Forces recreation and restart of the language server for the given language.
It is assumed that the language server for the given language is no longer running.
:param language: the language
:return: the newly created language server
"""
if language not in self._language_servers:
raise ValueError(f"No language server for language {language.value} present; cannot restart")
return self._create_and_start_language_server(language)
def add_language_server(self, ls_id: LanguageServerId) -> SolidLanguageServer:
"""
Dynamically adds a new language server for the given language.
:param ls_id: the language server to add
:return: the newly created language server
"""
if ls_id in self._language_servers:
raise ValueError(f"Language server for language {ls_id.value} already present")
return self._create_and_start_language_server(ls_id)
def remove_language_server(self, language: LanguageServerId, save_cache: bool = False) -> None:
"""
Removes the language server for the given language, stopping it if it is running.
:param language: the language
"""
if language not in self._language_servers:
raise ValueError(f"No language server for language {language.value} present; cannot remove")
ls = self._language_servers.pop(language)
self._stop_language_server(ls, save_cache=save_cache)
def get_active_language_server_ids(self) -> list[LanguageServerId]:
"""
Returns the list of languages for which language servers are currently managed.
:return: list of languagesView on GitHub (pinned to 7fcbca7e62)
Solutions
- Check ls_id in get_active_language_server_ids() before adding
- If replacement is intended, call remove_language_server(ls_id) first, then add_language_server
- Reuse the existing server via get_language_server for a representative file
- Wrap in try/except ValueError and treat 'already present' as success
Example fix
// before
manager.add_language_server(LanguageServerId.PYTHON)
# second call raises ValueError
manager.add_language_server(LanguageServerId.PYTHON)
// after
if LanguageServerId.PYTHON not in manager.get_active_language_server_ids():
manager.add_language_server(LanguageServerId.PYTHON) Defensive patterns
Strategy: validation
Validate before calling
if ls_id in manager.get_active_language_server_ids():
manager.remove_language_server(ls_id)
manager.add_language_server(ls_id) Try / catch
try:
manager.add_language_server(ls_id)
except ValueError as e:
if "already present" in str(e):
pass # treat as success
else:
raise Prevention
- Check active ids before adding
- Only call add_language_server for genuinely new languages
- For replacement, remove first then add
- Make idempotent startup code that tolerates 'already present'
When it happens
Trigger: Calling add_language_server(ls_id) twice; calling add for a language already started by from_languages; _ensure_functional_ls recovery logic racing with a user-initiated add.
Common situations: Startup code unconditionally adds servers after from_languages already created them; retry logic re-adding after a partial failure where the server actually started; plugin enabling a language that's already enabled.
Related errors
- No language server for language {language.value} present; ca
- No language server for language {language.value} present; ca
- No symbols found in target file {target_file}
- FindSymbolTool returned no results
- Unhandled document change kind: {change}; Please report to S
AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29).
Data as JSON: /api/errors/0ac917f7db4400c1.
Report an issue: GitHub.