oraios/serena · error · PluginServerError
Unexpected response from readFile: {response}
Error message
Unexpected response from readFile: {response} What it means
JetBrainsPluginClient raises PluginServerError when the JetBrains IDE plugin's /readFile HTTP endpoint returns a JSON response lacking a 'content' key. The client treats any response without 'content' as a protocol violation or unexpected plugin state, so it refuses to return a value.
Source
Thrown at src/serena/jetbrains/jetbrains_plugin_client.py:744
:param language: optional language to filter inspections by (e.g. "Java", "Python")
:param group_path_contains: optional substring to filter inspection group paths
"""
self._require_version_at_least(2023, 2, 14)
request_data: dict[str, Any] = {}
if language is not None:
request_data["language"] = language
if group_path_contains is not None:
request_data["groupPathContains"] = group_path_contains
return cast(jb.ListInspectionsResponse, self._make_request("POST", "/listInspections", request_data))
def read_file(self, relative_path: str) -> str:
self._require_version_at_least(2023, 3, 3)
request_data = {
"relativePath": relative_path,
}
response = self._make_request("POST", "/readFile", request_data)
if "content" not in response:
raise PluginServerError(f"Unexpected response from readFile: {response}")
return response["content"]
def close(self) -> None:
self._session.close()
def __enter__(self) -> Self:
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
View on GitHub (pinned to 7fcbca7e62)
Solutions
- Verify the relative_path exists inside the JetBrains project root before calling read_file
- Catch PluginServerError and fall back to local filesystem read
- Update the JetBrains plugin and serena to matching versions so the /readFile response schema matches
- Log the full response payload to see the error detail the plugin returned
Example fix
// before
content = client.read_file("src/missing.py")
// after
from pathlib import Path
p = project_root / "src/missing.py"
if not p.is_file():
raise FileNotFoundError(f"{p} does not exist")
try:
content = client.read_file("src/missing.py")
except PluginServerError as e:
content = p.read_text() Defensive patterns
Strategy: try-catch
Validate before calling
from pathlib import Path
p = Path(project_root) / relative_path
if not p.is_file():
raise FileNotFoundError(relative_path) Type guard
def has_content(resp: dict) -> bool:
return isinstance(resp, dict) and isinstance(resp.get("content"), str) Try / catch
try:
content = client.read_file(relative_path)
except PluginServerError as e:
logger.warning("readFile failed: %s", e)
content = (project_root / relative_path).read_text() Prevention
- Verify the file exists under the project root before calling
- Keep serena and the JetBrains plugin versions in sync
- Inspect the response payload in the exception message for the plugin's error detail
- Fall back to direct filesystem reads for non-editor-critical paths
When it happens
Trigger: Calling read_file(relative_path=...) when the plugin returns an error payload (e.g. {'error': 'file not found'}), an empty object, or an unexpected schema instead of {'content': ...}. Typically the file does not exist, is outside the project root, or the plugin version's response shape differs.
Common situations: Requesting a deleted or renamed file; path outside the opened JetBrains project; plugin version mismatch changing the response format; the IDE returning an error JSON for unreadable/binary files.
Related errors
- This operation requires Serena JetBrains plugin version {'.'
- No symbol with name {name_path} found in file {relative_file
- Found multiple {len(symbols)} symbols with name {name_path}
- Found no Serena service in a JetBrains IDE instance for the
- Failed to connect to Serena service at {url}: {e}
AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29).
Data as JSON: /api/errors/8389838143ffced6.
Report an issue: GitHub.