From 882664f70b4a12fa00150a1f1b596cd2461acc9e Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 13:59:24 +0000 Subject: [PATCH] fix(providers): match google submodule imports and walk full exception chain Co-Authored-By: Ahmed Allam --- strix/interface/main.py | 20 ++++++++++++++------ tests/test_provider_hints.py | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/strix/interface/main.py b/strix/interface/main.py index 39758f31..54041818 100644 --- a/strix/interface/main.py +++ b/strix/interface/main.py @@ -62,7 +62,7 @@ BEDROCK_EXTRA_HINT = ( 'Bedrock support is optional. Install it with: pipx install "strix-agent[bedrock]"' ) VERTEX_MODEL_MARKER = "vertex" -VERTEX_MISSING_MODULE_ERROR = "No module named 'google'" +VERTEX_MISSING_MODULE_ERROR = "No module named 'google" VERTEX_EXTRA_HINT = ( 'Vertex AI support is optional. Install it with: pipx install "strix-agent[vertex]"' ) @@ -225,11 +225,19 @@ def check_docker_installed() -> None: def _exception_messages(exc: BaseException) -> tuple[str, ...]: - messages = [str(exc)] - if exc.__cause__ is not None: - messages.append(str(exc.__cause__)) - if exc.__context__ is not None: - messages.append(str(exc.__context__)) + messages: list[str] = [] + seen: set[int] = set() + stack: list[BaseException] = [exc] + while stack: + current = stack.pop() + if id(current) in seen: + continue + seen.add(id(current)) + messages.append(str(current)) + if current.__cause__ is not None: + stack.append(current.__cause__) + if current.__context__ is not None: + stack.append(current.__context__) return tuple(messages) diff --git a/tests/test_provider_hints.py b/tests/test_provider_hints.py index 7849aa58..437c1e10 100644 --- a/tests/test_provider_hints.py +++ b/tests/test_provider_hints.py @@ -46,6 +46,25 @@ def test_bedrock_boto3_hint_for_litellm_wrapped_connection_error() -> None: assert BEDROCK_EXTRA_NAME in hint +def test_vertex_google_submodule_hint() -> None: + exc = ModuleNotFoundError("No module named 'google.auth'") + hint = _provider_import_hint(exc, VERTEX_MODEL) + assert hint is not None + assert INSTALL_EXTRA_COMMAND_FRAGMENT in hint + assert VERTEX_EXTRA_NAME in hint + + +def test_vertex_google_hint_for_deeply_chained_error() -> None: + root = ModuleNotFoundError("No module named 'google.auth'") + middle = RuntimeError("provider init failed") + middle.__cause__ = root + exc = ConnectionError("litellm.APIConnectionError: request failed") + exc.__cause__ = middle + hint = _provider_import_hint(exc, VERTEX_MODEL) + assert hint is not None + assert VERTEX_EXTRA_NAME in hint + + def test_non_import_error_returns_none() -> None: assert _provider_import_hint(ConnectionError("boom"), "bedrock/whatever") is None