Skip to content

from_provider("google/...") masks httpx SOCKS ImportError as “google-genai package is required” #1940

@mading0817

Description

@mading0817

Generated by ChatGPT:


Description

When using instructor.from_provider("google/...") together with google-genai and a SOCKS proxy, any ImportError raised inside the Google provider init is turned into a generic:

The google-genai package is required to use the Google provider.
Install it with pip install google-genai.

In my case google-genai was installed and importable. The actual underlying error was coming from httpx complaining about missing socksio, but that information was completely hidden by the broad except ImportError in from_provider.

This makes it very hard to diagnose configuration issues that are not related to google-genai being missing.


Environment

  • OS: Windows 11 (x64)

  • Python: 3.11.9

  • Virtualenv: yes (.venv for the project)

  • instructor: 1.13.0 (installed as instructor[google-genai]>=1.13.0,<2.0)

  • google-genai: installed via pip, importable as google.genai

  • Network:

    • System-level / process-level SOCKS proxy (v2Ray)
    • Standard HTTP(S)_PROXY / ALL_PROXY env vars pointing to socks5://127.0.0.1:PORT
  • No socksio / httpx[socks] installed initially


Minimal repro

With the environment above:

import instructor

# google-genai is already installed and importable

client = instructor.from_provider("google/gemini-2.5-flash", api_key="dummy")

Result:

instructor.core.exceptions.ConfigurationError:
The google-genai package is required to use the Google provider.
Install it with `pip install google-genai`.

This looks like a dependency issue with google-genai, but that’s not actually the problem.


What I verified

  1. The interpreter & venv are correct

    python -c "import sys; print(sys.executable)"
    # -> points to .venv/Scripts/python.exe
  2. google-genai imports fine

    import google.genai as genai
    from google.genai import types
    
    print("GENAI_FILE:", genai.__file__)
    print("TYPES_FILE:", types.__file__)

    This succeeds and prints valid paths under .venv/Lib/site-packages/google/genai.

  3. from_genai is present and importable

    from instructor import from_genai

    This also succeeds.

  4. Directly constructing a genai.Client shows the real error

    from google import genai
    
    client = genai.Client(api_key="dummy")

    This fails with:

    ImportError: Using SOCKS proxy, but the 'socksio' package is not installed.
    Make sure to install httpx using `pip install httpx[socks]`.
    

    The stack trace shows this originates from httpx inside google.genai’s BaseApiClient, when it tries to set up the HTTP client while a SOCKS proxy is configured.

  5. Looking at from_provider for the Google branch

    In auto_client.py (shortened to the relevant part):

    elif provider == "google":
        try:
            import google.genai as genai
            from instructor import from_genai
            import os
    
            # ... compute api_key, client_kwargs, etc ...
    
            client = genai.Client(
                vertexai=vertexai_flag,
                api_key=api_key,
                **client_kwargs,
            )
    
            if async_client:
                result = from_genai(
                    client,
                    use_async=True,
                    model=model_name,
                    mode=mode if mode else instructor.Mode.GENAI_TOOLS,
                    **kwargs,
                )
            else:
                result = from_genai(
                    client,
                    model=model_name,
                    mode=mode if mode else instructor.Mode.GENAI_TOOLS,
                    **kwargs,
                )
            return result
    
        except ImportError:
            from .core.exceptions import ConfigurationError
    
            raise ConfigurationError(
                "The google-genai package is required to use the Google provider. "
                "Install it with `pip install google-genai`."
            ) from None

    The whole block (including the genai.Client(...) call) is inside try: ... except ImportError:.

    So any ImportError (including ones thrown by httpx or other transitive dependencies) is treated as “google-genai is not installed”.


Root cause

  • In my environment, genai.Client(...) internally calls httpx to create an HTTP client.

  • Because a SOCKS proxy is configured but socksio/httpx[socks] is not installed, httpx raises:

    ImportError: Using SOCKS proxy, but the 'socksio' package is not installed.
    Make sure to install httpx using `pip install httpx[socks]`.
    
  • This ImportError is caught by the broad except ImportError: in from_provider, which assumes that any ImportError must mean “google-genai is missing”.

  • The original error message and stack trace are discarded (from None), and a ConfigurationError with the misleading “The google-genai package is required…” message is raised instead.

So the actual fix on my side was simply to install socks support:

pip install "httpx[socks]"
# which brings in `socksio`

After that, both:

from google import genai
from instructor import from_genai, Mode

client = genai.Client(api_key="dummy")
wrapped = from_genai(client, model="gemini-2.5-flash", mode=Mode.GENAI_TOOLS)
# OK

import instructor
client = instructor.from_provider("google/gemini-2.5-flash", api_key="dummy")
# OK

work correctly.

But it took a lot of digging to realize the problem was missing socksio, not google-genai.


Expected behavior

Instead of unconditionally telling the user to install google-genai, I’d expect one of:

  1. More precise exception handling

    Only catch import errors around the actual imports:

    try:
        import google.genai as genai
        from instructor import from_genai
    except ImportError as e:
        from .core.exceptions import ConfigurationError
        raise ConfigurationError(
            "The google-genai package is required to use the Google provider. "
            "Install it with `pip install google-genai`."
        ) from e
    
    # then, outside the try/except:
    client = genai.Client(...)

    This way, runtime errors from genai.Client(...) (including ImportError from httpx internals) are not misreported as “google-genai missing”.

  2. Or at least preserve the original cause and soften the message

    For example:

    except ImportError as e:
        from .core.exceptions import ConfigurationError
        raise ConfigurationError(
            "Failed to import google-genai or one of its dependencies "
            "for the Google provider. Original error: "
            f"{e.__class__.__name__}: {e}"
        ) from e

    That would immediately show something like:

    ConfigurationError: Failed to import google-genai or one of its dependencies...
    Original error: ImportError: Using SOCKS proxy, but the 'socksio' package is not installed...
    

    which makes the root cause obvious.


Why this matters

  • The current behavior makes it look like a simple “install google-genai” problem, even when google-genai is correctly installed and the real issue is in a transitive dependency (httpx + SOCKS).

  • This is especially confusing in environments that:

    • already use instructor[google-genai] in pyproject.toml, and
    • verify google.genai is importable before calling from_provider.

A small change to the try/except structure (or to the error message) would make issues like “missing socksio when using a SOCKS proxy” much easier to diagnose.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdependenciesPull requests that update a dependency file

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions