Description
with_structured_output(schema, method="function_calling") raises AttributeError: 'NoneType' object has no attribute 'get' inside _prepare_request when schema is a dict that does not have a top-level "title" key.
Minimal Repro
from langchain_google_genai import ChatGoogleGenerativeAI
llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash-001")
# No "title" key — this crashes
schema = {
"type": "object",
"properties": {
"answer": {"type": "string"},
"score": {"anyOf": [{"type": "number"}, {"type": "null"}]},
},
"required": ["answer"],
}
structured = llm.with_structured_output(schema, method="function_calling")
structured.invoke("What weighs more, a pound of bricks or a pound of feathers?")
Error:
File ".../langchain_google_genai/_function_utils.py", line 404, in _format_to_genai_function_declaration
elif "parameters" in tool and tool["parameters"].get("properties"):
^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'get'
A dict schema with "title" works fine:
schema = {"title": "MyOutput", "type": "object", "properties": {...}, "required": [...]}
Root Cause
Two problems compound in bind_tools + _prepare_request:
Problem 1 — bind_tools fallback produces a broken FunctionDeclaration
# ChatGoogleGenerativeAI.bind_tools (chat_models.py ~line 66)
try:
formatted_tools = [convert_to_openai_tool(tool) for tool in tools]
except Exception:
formatted_tools = [tool_to_dict(t) for t in convert_to_genai_function_declarations(tools)]
convert_to_openai_tool raises ValueError: must have a top-level 'title' key for titleless dicts. The except Exception fallback calls convert_to_genai_function_declarations([titleless_schema]).
Inside _format_to_genai_function_declaration, the schema has no "name", "description", or "parameters" keys, so it falls into the else branch, sets function["parameters"] = {}, and _format_dict_to_function_declaration can't find a name → FunctionDeclaration(name="MISSING_NAME", parameters=None).
tool_to_dict serialises this as:
{"function_declarations": [{"name": "MISSING_NAME", "parameters": null}]}
Problem 2 — Missing None guard in _format_to_genai_function_declaration
When _prepare_request calls convert_to_genai_function_declarations a second time on the stored {"function_declarations": [...]} tools, it iterates over the function declarations and calls _format_to_genai_function_declaration({"name": "MISSING_NAME", "parameters": null}).
Line 404 (_function_utils.py):
elif "parameters" in tool and tool["parameters"].get("properties"):
"parameters" in tool is True (the key exists, value is null), but tool["parameters"] is None — calling .get() on it crashes.
Fix
Either problem fixed independently would prevent the crash. The minimal correct fix is adding a None guard:
# _function_utils.py line ~404
elif "parameters" in tool and tool["parameters"] is not None and tool["parameters"].get("properties"):
A more complete fix would also make the fallback path in bind_tools raise a clearer error (or handle the missing-title case) instead of silently producing FunctionDeclaration(name="MISSING_NAME", parameters=None).
Environment
langchain-google-genai version: checked against current main
- Python 3.12
Description
with_structured_output(schema, method="function_calling")raisesAttributeError: 'NoneType' object has no attribute 'get'inside_prepare_requestwhenschemais a dict that does not have a top-level"title"key.Minimal Repro
Error:
A dict schema with
"title"works fine:Root Cause
Two problems compound in
bind_tools+_prepare_request:Problem 1 —
bind_toolsfallback produces a brokenFunctionDeclarationconvert_to_openai_toolraisesValueError: must have a top-level 'title' keyfor titleless dicts. Theexcept Exceptionfallback callsconvert_to_genai_function_declarations([titleless_schema]).Inside
_format_to_genai_function_declaration, the schema has no"name","description", or"parameters"keys, so it falls into theelsebranch, setsfunction["parameters"] = {}, and_format_dict_to_function_declarationcan't find a name →FunctionDeclaration(name="MISSING_NAME", parameters=None).tool_to_dictserialises this as:{"function_declarations": [{"name": "MISSING_NAME", "parameters": null}]}Problem 2 — Missing
Noneguard in_format_to_genai_function_declarationWhen
_prepare_requestcallsconvert_to_genai_function_declarationsa second time on the stored{"function_declarations": [...]}tools, it iterates over the function declarations and calls_format_to_genai_function_declaration({"name": "MISSING_NAME", "parameters": null}).Line 404 (
_function_utils.py):"parameters" in toolisTrue(the key exists, value isnull), buttool["parameters"]isNone— calling.get()on it crashes.Fix
Either problem fixed independently would prevent the crash. The minimal correct fix is adding a
Noneguard:A more complete fix would also make the fallback path in
bind_toolsraise a clearer error (or handle the missing-title case) instead of silently producingFunctionDeclaration(name="MISSING_NAME", parameters=None).Environment
langchain-google-genaiversion: checked against currentmain