oraios/serena · error · PluginServerError

API request failed with HTTP error: {e}

Error message

API request failed with HTTP error: {e}

What it means

When requests raises an HTTPError but the response object is unavailable (response is None), _make_request raises PluginServerError('API request failed with HTTP error: {e}') — the request failed at HTTP level without a usable response body to inspect or classify as recoverable.

Source

Thrown at src/serena/jetbrains/jetbrains_plugin_client.py:357

        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]
            else:

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Retry the request; transient connection drops resolve after the plugin service settles
  2. Restart the IDE/plugin service if it recurs
  3. Check proxy/localhost networking as in connection errors
  4. Update the plugin and client to matched versions
Defensive patterns

Strategy: try-catch

Try / catch

try:
    overview = client.get_symbols_overview(relative_path="src")
except (PluginServerError, ConnectionError) as e:
    log.warning("Plugin request failed (%s); retrying once", e)
    overview = retry_once(lambda: client.get_symbols_overview(relative_path="src"))

Prevention

When it happens

Trigger: HTTP-level failure where response was never assigned/available in the except block, e.g. errors raised before a response was fully received; typically seen from the same callers (init, find_symbol, move, find_references, get_symbols_overview, get_supertypes).

Common situations: Malformed responses/connection drops mid-exchange; plugin service restarting between connect and response; unusual proxy behavior.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29). Data as JSON: /api/errors/c840ec32ff506084. Report an issue: GitHub.