{"record":{"id":"2bd902d2693ff419","repo":"JuliusBrussee/caveman","slug":"expected-a-native-google-chat-or-asyncchat","errorCode":null,"errorMessage":"Expected a native Google Chat or AsyncChat","messagePattern":"Expected a native Google Chat or AsyncChat","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/middleware/python/caveman_middleware/google.py","lineNumber":181,"sourceCode":"    \"\"\"\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()\n    if not isinstance(runtime, AsyncMiddlewareRuntime if asynchronous else MiddlewareRuntime):\n        raise TypeError(\"Match the sync/async runtime to the chat\")\n    if not supports_framework(runtime, (\"google-genai\", \"2.22\", \"3\")):\n        return chat\n    send, stream, default = chat.send_message, chat.send_message_stream, config\n    if asynchronous:\n        @functools.wraps(send)\n        async def send_message(message, config=None):\n            selected, context = _bind(config if config is not None else default, runtime, scope, asynchronous=True)\n            token = _invocation.set(context)\n            try:\n                return await send(message, config=selected)\n            finally:\n                _invocation.reset(token)\n\n        @functools.wraps(stream)","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/middleware/python/caveman_middleware/google.py#L163-L199","documentation":"with_caveman_google_chat instruments a google.genai Chat or AsyncChat. The chat argument is type-checked against both classes and this TypeError is raised for anything else, since the wrapper needs the chat's send_message/send_message_stream methods to register hooks.","triggerScenarios":"Passing a genai.Client, a Models interface, or any non-Chat object as `chat` to with_caveman_google_chat — e.g. wrapping the client instead of the chat session created via client.chats.create().","commonSituations":"Confusing Client-level instrumentation with Chat-level instrumentation; passing a custom chat-like wrapper class that does not subclass Chat/AsyncChat; calling the chat entrypoint before creating the chat.","solutions":["Pass the Chat returned by client.chats.create(...) (or AsyncChat) to with_caveman_google_chat.","Use with_caveman_google on the Client if you want client-level (models) instrumentation instead.","Ensure your chat object is a genuine google.genai.chats.Chat/AsyncChat instance, not a duck-typed substitute."],"exampleFix":"// before\nwith_caveman_google_chat(client, runtime, scope)\n// after\nchat = client.chats.create(model=\"gemini-2.0-flash\")\nwith_caveman_google_chat(chat, runtime, scope)","handlingStrategy":"type-guard","validationCode":"from google.genai.chats import Chat, AsyncChat\nif not isinstance(chat, (Chat, AsyncChat)):\n    raise TypeError(\"with_caveman_google_chat requires a Chat or AsyncChat\")","typeGuard":"def is_native_chat(obj) -> bool:\n    from google.genai.chats import Chat, AsyncChat\n    return isinstance(obj, (Chat, AsyncChat))","tryCatchPattern":"try:\n    chat = with_caveman_google_chat(chat, runtime, scope)\nexcept TypeError as e:\n    if \"native Google Chat\" in str(e):\n        raise ConfigError(\"Wrap the chat from client.chats.create(), not the client\") from e\n    raise","preventionTips":["Create chats via client.chats.create(...) and wrap that object.","Use with_caveman_google for Client-level instrumentation instead.","Avoid custom duck-typed chat wrappers; subclass or use native Chat.","Instrument at one level (client OR chat) per application path."],"tags":["google","genai","chat","type-check"],"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"}