oraios/serena · error · SystemExit

Failed to set up Serena for {client}.

Error message

Failed to set up Serena for {client}.

What it means

After the applicability check passes, `serena setup <client>` calls handler.apply() to write the Serena MCP server entry into the client's config. A False return means apply() failed (e.g. could not read/parse/write the config file); the CLI prints this message and exits with SystemExit(1). Unlike error 15, the client was detected but the write/apply step failed.

Source

Thrown at src/serena/cli.py:230

    @click.argument(
        "client",
        type=click.Choice([h.name for h in client_setup_handlers]),
    )
    def setup(client: str) -> None:
        # find the matching handler
        handler = next(h for h in client_setup_handlers if h.name == client)

        # check applicability
        if not handler.is_applicable():
            click.echo(f"\nCannot apply setup for client '{client}' (not found or not functional).\n")
            raise SystemExit(1)

        # apply the setup
        if handler.apply():
            click.echo(f"\nSerena has been successfully set up for {client}.\n")
        else:
            click.echo(f"\nFailed to set up Serena for {client}.\n")
            raise SystemExit(1)

    @staticmethod
    @click.command("start-mcp-server", help="Starts the Serena MCP server.", context_settings={"max_content_width": _MAX_CONTENT_WIDTH})
    @click.option("--project", "project", type=PROJECT_TYPE, default=None, help="Path or name of project to activate at startup.")
    @click.option("--project-file", "project", type=PROJECT_TYPE, default=None, help="[DEPRECATED] Use --project instead.")
    @click.argument("project_file_arg", type=PROJECT_TYPE, required=False, default=None, metavar="")
    @click.option(
        "--context", type=str, default=DEFAULT_CONTEXT, show_default=True, help="Built-in context name or path to custom context YAML."
    )
    @click.option(
        "--mode",
        "default_modes",
        type=str,
        multiple=True,
        default=(),
        show_default=False,
        help=_MODES_EXPLANATION,
    )

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Validate/fix the client's MCP config file (remove JSON/YAML syntax errors, e.g. via a JSON linter) and rerun the setup command.
  2. Add the Serena server entry manually to the client's MCP config if automated patching keeps failing.
  3. Check file permissions/ownership of the client config directory; run with adequate rights (not necessarily sudo).
  4. Back up and regenerate the client config, then rerun `serena setup <client>`.

Example fix

// before: ~/.claude.json has a trailing comma -> parse fails
{"mcpServers": {"a": {"command": "x",},}}
// after: valid JSON
{"mcpServers": {"a": {"command": "x"}}}   // then rerun: serena setup claude-code
Defensive patterns

Strategy: try-catch

Validate before calling

import json
def client_config_valid(path: str) -> bool:
    if not os.path.exists(path):
        return False
    try:
        with open(path) as f:
            json.load(f)
        return os.access(path, os.W_OK)
    except (json.JSONDecodeError, OSError):
        return False

Try / catch

try:
    ok = handler.apply()
except SystemExit:
    raise
if not ok:
    log.error('Apply failed; fix %s manually or add the serena MCP entry by hand')

Prevention

When it happens

Trigger: Running `serena setup <client>` where the handler's apply() returns False — typically a corrupt or unparseable client config file, permission errors writing the config, or missing expected keys/paths inside an existing config.

Common situations: Invalid JSON/YAML in the client's MCP config (manual edits, merge conflicts); read-only config directory; config schema changed in a newer client version so the handler can't patch it; disk full or antivirus locking the file.

Related errors


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