fix(cli): print friendly error instead of traceback when proxy is unreachable

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
ryan 2026-07-15 22:45:19 +00:00
parent 9121ae3024
commit bb8b8f48c8
2 changed files with 41 additions and 1 deletions

View file

@ -3,6 +3,7 @@ from typing import Optional
# third party imports
import click
import requests
from litellm._version import version as litellm_version
from litellm.proxy.client.health import HealthManagementClient
@ -22,6 +23,20 @@ from .commands.users import users
from .interface import interactive_shell
class ConnectionAwareGroup(click.Group):
def invoke(self, ctx: click.Context) -> object:
try:
return super().invoke(ctx)
except requests.exceptions.ConnectionError as e:
base_url = ctx.obj.get("base_url") if isinstance(ctx.obj, dict) else None
target = f" at {base_url}" if base_url else ""
raise click.ClickException(
f"Could not connect to the LiteLLM proxy{target}. "
"Make sure the server is running and reachable, or point the CLI at it "
"with --base-url or the LITELLM_PROXY_URL environment variable."
) from e
def print_version(base_url: str, api_key: Optional[str]):
"""Print CLI and server version info."""
click.echo(f"LiteLLM Proxy CLI Version: {litellm_version}")
@ -38,7 +53,7 @@ def print_version(base_url: str, api_key: Optional[str]):
click.echo(f"Could not retrieve server version: {e}")
@click.group(invoke_without_command=True)
@click.group(cls=ConnectionAwareGroup, invoke_without_command=True)
@click.option(
"--version",
"-v",

View file

@ -4,6 +4,7 @@ import sys
from unittest.mock import Mock, patch
import pytest
import requests
from click.testing import CliRunner
sys.path.insert(
@ -65,6 +66,30 @@ def test_base_url_trailing_slash_normalized(cli_runner):
)
@pytest.mark.parametrize(
"args",
[
["models", "list"],
["keys", "list"],
["http", "request", "GET", "/models"],
],
)
def test_connection_error_prints_friendly_message(cli_runner, args):
"""A dead proxy must yield a friendly 'Error:' line and exit 1, not a raw traceback."""
base_url = "http://127.0.0.1:59999"
with patch(
"requests.sessions.Session.request",
side_effect=requests.exceptions.ConnectionError("connection refused"),
):
result = cli_runner.invoke(cli, ["--base-url", base_url, *args])
assert result.exit_code == 1
assert "Traceback" not in result.output
assert f"Could not connect to the LiteLLM proxy at {base_url}" in result.output
# The exception must be swallowed into a click exit, never surfaced raw.
assert not isinstance(result.exception, requests.exceptions.ConnectionError)
def test_cli_version_command(cli_runner):
"""Test that 'version' command prints the correct version, server URL, and server version, and exits successfully"""
with (