{"record":{"id":"9303ab5e802430fe","repo":"JuliusBrussee/caveman","slug":"expected-a-google-client-and-synchronous-middlewareruntime","errorCode":null,"errorMessage":"Expected a Google Client and synchronous MiddlewareRuntime","messagePattern":"Expected a Google Client and synchronous MiddlewareRuntime","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/middleware/python/caveman_middleware/google.py","lineNumber":165,"sourceCode":"            finally:\n                _invocation.reset(token)\n\n        @functools.wraps(stream)\n        def generate_content_stream(*, model, contents, config=None):\n            config, context = _bind(config, runtime, scope)\n            return _scope_iterator(stream(model=model, contents=list(contents) if type(contents) is list else contents, config=config), context)\n    module.generate_content, module.generate_content_stream = generate_content, generate_content_stream\n\n\ndef with_caveman_google(client, *, runtime, scope):\n    \"\"\"Register native model AFC on an existing, transport-configured Client.\n\n    This is instance-scoped registration on public methods. Construct the client\n    with the transports below; existing auth and client options remain native.\n    Use with_caveman_google_chat for a Chat, which owns a separate AFC loop.\n    \"\"\"\n    if not isinstance(client, genai.Client) or not isinstance(runtime, MiddlewareRuntime):\n        raise TypeError(\"Expected a Google Client and synchronous MiddlewareRuntime\")\n    if not supports_framework(runtime, (\"google-genai\", \"2.22\", \"3\")):\n        return client\n    _wrap_model(client.models, runtime, scope)\n    _wrap_model(client.aio.models, runtime.as_async(), scope, True)\n    return client\n\n\ndef with_caveman_google_chat(chat, *, runtime, scope, config=None):\n    \"\"\"Register recovery in an existing native Chat/AsyncChat's own AFC loop.\n\n    Pass the original default config here, or supply config on each send. No\n    private chat configuration/history is read or modified.\n    \"\"\"\n    asynchronous = isinstance(chat, AsyncChat)\n    if not isinstance(chat, (Chat, AsyncChat)):\n        raise TypeError(\"Expected a native Google Chat or AsyncChat\")\n    if asynchronous and isinstance(runtime, MiddlewareRuntime):\n        runtime = runtime.as_async()","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/middleware/python/caveman_middleware/google.py#L147-L183","documentation":"with_caveman_google instruments a google.genai.Client's models interfaces. It requires the first argument to be an actual genai.Client instance and the runtime to be a synchronous MiddlewareRuntime; anything else is rejected with this TypeError before any wrapping happens.","triggerScenarios":"Passing a non-Client object (e.g. a Models interface, a Chat, a config dict, or None) as client, or an AsyncMiddlewareRuntime (or a plain dict/string) as runtime to with_caveman_google.","commonSituations":"Wrapping client.models instead of client; using the async runtime obtained for aio usage with the sync entrypoint; constructing the Client lazily and passing a factory/future; mixing up with_caveman_google and with_caveman_google_chat arguments.","solutions":["Pass the genai.Client itself: with_caveman_google(client, runtime, scope).","Pass a synchronous MiddlewareRuntime; use runtime.as_async()/the async entrypoint for aio paths.","Use with_caveman_google_chat if you actually have a Chat/AsyncChat rather than a Client."],"exampleFix":"// before\nwith_caveman_google(client.models, async_runtime, scope)\n// after\nwith_caveman_google(client, sync_runtime, scope)","handlingStrategy":"type-guard","validationCode":"from google import genai\nfrom caveman_cloud.middleware import MiddlewareRuntime\nif not isinstance(client, genai.Client) or not isinstance(runtime, MiddlewareRuntime):\n    raise TypeError(\"with_caveman_google requires genai.Client + sync MiddlewareRuntime\")","typeGuard":"def valid_google_args(client, runtime) -> bool:\n    from google import genai\n    from caveman_cloud.middleware import MiddlewareRuntime\n    return isinstance(client, genai.Client) and isinstance(runtime, MiddlewareRuntime)","tryCatchPattern":"try:\n    client = with_caveman_google(client, runtime, scope)\nexcept TypeError as e:\n    if \"Google Client\" in str(e):\n        raise ConfigError(\"Pass the genai.Client itself and a sync runtime\") from e\n    raise","preventionTips":["Pass the Client object, never client.models or a chat.","Keep separate sync/async runtimes and use the right one per entrypoint.","Build Clients eagerly so you always wrap a real instance.","Add argument assertions in your middleware bootstrap helper."],"tags":["google","genai","type-check","runtime"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}