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

  1. Read the response.text in the error — it usually contains the IDE-side stacktrace or message
  2. Update the Serena plugin to match the client's expected API surface
  3. Reopen the project in the IDE and retry
  4. 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

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


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