oraios/serena · error · PluginServerError
API request failed with status {response.status_code}: {resp
Error message
API request failed with status {response.status_code}: {response.text} What it means
When the plugin returns an HTTP error that is NOT deemed recoverable (status != 400 for plugin >=2023.2.6, or response is None), _make_request raises PluginServerError('API request failed with status {status}: {body}'), surfacing the IDE-side error text.
Source
Thrown at src/serena/jetbrains/jetbrains_plugin_client.py:356
return {"response": response.text}
except requests.exceptions.ConnectionError as e:
raise ConnectionError(f"Failed to connect to Serena service at {url}: {e}")
except requests.exceptions.Timeout as e:
raise ConnectionError(f"Request to {url} timed out: {e}")
except requests.exceptions.HTTPError as e:
if response is not None:
# check for recoverable error (i.e. errors where the problem can be resolved by the caller or
# other errors where the error text shall simply be passed on to the LLM).
# The plugin returns 400 for such errors (typically illegal arguments, e.g. non-unique name path)
# but only since version 2023.2.6
if self.is_version_at_least(2023, 2, 6):
is_recoverable_error = response.status_code == 400
else:
is_recoverable_error = True # assume recoverable for older versions (mix of errors)
if is_recoverable_error:
raise APIError(response)
raise PluginServerError(f"API request failed with status {response.status_code}: {response.text}")
raise PluginServerError(f"API request failed with HTTP error: {e}")
except requests.exceptions.RequestException as e:
raise SerenaClientError(f"Request failed: {e}")
@staticmethod
def _pythonify_response(response: T) -> T:
"""
Converts dictionary keys from camelCase to snake_case recursively.
:response: the response in which to convert keys (dictionary or list)
"""
to_snake_case = lambda s: "".join(["_" + c.lower() if c.isupper() else c for c in s])
def convert(x):
if isinstance(x, dict):
return {to_snake_case(k): convert(v) for k, v in x.items()}
elif isinstance(x, list):
return [convert(item) for item in x]View on GitHub (pinned to 7fcbca7e62)
Solutions
- Read the response.text in the error — it usually contains the IDE-side stacktrace or message
- Update the Serena plugin to match the client's expected API surface
- Reopen the project in the IDE and retry
- Report a plugin bug with the status code and body if 500 persists
Defensive patterns
Strategy: try-catch
Validate before calling
# no pre-call validation possible; log and inspect server-side details on failure
def describe(err: PluginServerError) -> str:
return str(err) # contains HTTP status and response body from the IDE plugin Try / catch
try:
client.move(...) # or other plugin op
except PluginServerError as e:
log.error("Plugin HTTP failure: %s", e) # includes status code + body
if "404" in str(e):
suggest_plugin_update()
raise Prevention
- Keep the JetBrains plugin and serena client versions matched to avoid unknown endpoints
- Read the error body — it contains the IDE-side cause
- Reopen the project in the IDE if the service reports the project is missing
- Report persistent 500s to the Serena plugin issue tracker with logs
When it happens
Trigger: Plugin service responding 4xx/5xx other than 400 (e.g. 404 unknown endpoint for old plugin, 500 internal IDE error, 401/403) to calls like find_symbol, move, or get_symbols_overview.
Common situations: Plugin version mismatch so the endpoint path doesn't exist (404); IDE-internal exception during refactorings (500); plugin service bound but project closed on the IDE side.
Related errors
- API request failed with HTTP error: {e}
- Failed to connect to Serena service at {url}: {e}
- Request to {url} timed out: {e}
- Request failed: {e}
- No symbol with name {name_path} found in file {relative_file
AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29).
Data as JSON: /api/errors/6f237d09f28f7cab.
Report an issue: GitHub.