Bug Description
json_schema_to_pydantic_type() correctly maps a direct {"type": "null"} schema to Optional[Any], and it already preserves boolean|null or object|null unions. But when a top-level combiner collapses to only a null branch, the helper falls into its generic string fallback.
_build_union_from_options() marks the null branch with has_null=True, then returns str when no non-null branches remain. The earlier filtered_schema is None -> return str fallback does the same after boolean-schema filtering.
Schemas such as {"anyOf": [{"type": "null"}]} or {"anyOf": [false, {"type": "null"}]} are therefore converted into str-typed fields instead of nullable ones. Any model builder that delegates combiners to this helper then emits type: string for a schema that only permits null, and explicit None values are rejected by Pydantic.
Root Cause
python/composio/utils/schema_converter.py L146-149, L257-273:
filtered_schema = _filter_boolean_schemas(json_schema)
if filtered_schema is None:
return str # Fallback if all schemas were false
...
for option in options:
ptype = json_schema_to_pydantic_type(option)
if ptype is None:
continue
if ptype == null_type or ptype is type(None):
has_null = True
continue
pydantic_types.append(ptype)
if len(pydantic_types) == 0:
return str # Fallback — should be Optional[Any] when has_null=True
Steps to Reproduce
from composio.utils.schema_converter import json_schema_to_pydantic_type
# Direct null schema — works correctly
result = json_schema_to_pydantic_type({"type": "null"})
print(result) # Optional[Any] ✓
# Null-only anyOf — falls back to str instead of Optional[Any]
result = json_schema_to_pydantic_type({"anyOf": [{"type": "null"}]})
print(result) # str ✗ — should be Optional[Any]
Expected Behavior
When the only remaining branch in an anyOf/oneOf is null, the resulting type should be Optional[Any], not str.
Suggested Fix
When combiner processing sees at least one null branch and no remaining concrete branches, return Optional[Any] instead of str:
if len(pydantic_types) == 0:
return Optional[Any] if has_null else str
Discovered during code review.
Bug Description
json_schema_to_pydantic_type()correctly maps a direct{"type": "null"}schema toOptional[Any], and it already preservesboolean|nullorobject|nullunions. But when a top-level combiner collapses to only anullbranch, the helper falls into its generic string fallback._build_union_from_options()marks thenullbranch withhas_null=True, then returnsstrwhen no non-null branches remain. The earlierfiltered_schema is None -> return strfallback does the same after boolean-schema filtering.Schemas such as
{"anyOf": [{"type": "null"}]}or{"anyOf": [false, {"type": "null"}]}are therefore converted intostr-typed fields instead of nullable ones. Any model builder that delegates combiners to this helper then emitstype: stringfor a schema that only permitsnull, and explicitNonevalues are rejected by Pydantic.Root Cause
python/composio/utils/schema_converter.pyL146-149, L257-273:Steps to Reproduce
Expected Behavior
When the only remaining branch in an
anyOf/oneOfisnull, the resulting type should beOptional[Any], notstr.Suggested Fix
When combiner processing sees at least one
nullbranch and no remaining concrete branches, returnOptional[Any]instead ofstr:Discovered during code review.