{"record":{"id":"8389838143ffced6","repo":"oraios/serena","slug":"unexpected-response-from-readfile-response","errorCode":null,"errorMessage":"Unexpected response from readFile: {response}","messagePattern":"Unexpected response from readFile: (.+?)","errorType":"exception","errorClass":"PluginServerError","httpStatus":null,"severity":"error","filePath":"src/serena/jetbrains/jetbrains_plugin_client.py","lineNumber":744,"sourceCode":"        :param language: optional language to filter inspections by (e.g. \"Java\", \"Python\")\n        :param group_path_contains: optional substring to filter inspection group paths\n        \"\"\"\n        self._require_version_at_least(2023, 2, 14)\n        request_data: dict[str, Any] = {}\n        if language is not None:\n            request_data[\"language\"] = language\n        if group_path_contains is not None:\n            request_data[\"groupPathContains\"] = group_path_contains\n        return cast(jb.ListInspectionsResponse, self._make_request(\"POST\", \"/listInspections\", request_data))\n\n    def read_file(self, relative_path: str) -> str:\n        self._require_version_at_least(2023, 3, 3)\n        request_data = {\n            \"relativePath\": relative_path,\n        }\n        response = self._make_request(\"POST\", \"/readFile\", request_data)\n        if \"content\" not in response:\n            raise PluginServerError(f\"Unexpected response from readFile: {response}\")\n        return response[\"content\"]\n\n    def close(self) -> None:\n        self._session.close()\n\n    def __enter__(self) -> Self:\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        self.close()\n","sourceCodeStart":726,"sourceCodeEnd":755,"githubUrl":"https://github.com/oraios/serena/blob/7fcbca7e62555ec2287ddb2f083caee805848ea6/src/serena/jetbrains/jetbrains_plugin_client.py#L726-L755","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ncontent = client.read_file(\"src/missing.py\")\n// after\nfrom pathlib import Path\np = project_root / \"src/missing.py\"\nif not p.is_file():\n    raise FileNotFoundError(f\"{p} does not exist\")\ntry:\n    content = client.read_file(\"src/missing.py\")\nexcept PluginServerError as e:\n    content = p.read_text()","handlingStrategy":"try-catch","validationCode":"from pathlib import Path\np = Path(project_root) / relative_path\nif not p.is_file():\n    raise FileNotFoundError(relative_path)","typeGuard":"def has_content(resp: dict) -> bool:\n    return isinstance(resp, dict) and isinstance(resp.get(\"content\"), str)","tryCatchPattern":"try:\n    content = client.read_file(relative_path)\nexcept PluginServerError as e:\n    logger.warning(\"readFile failed: %s\", e)\n    content = (project_root / relative_path).read_text()","preventionTips":["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"],"tags":["jetbrains","http-response","plugin","file-read"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"7fcbca7e62555ec2287ddb2f083caee805848ea6","analyzedAt":"2026-08-29T00:04:09.619Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}