Skip to content

Property type comparison mutates schemas that combine a type list with anyOf #254

Description

@fede-kamel

Description

Comparing two property schemas, or checking whether one is castable to the other, silently mutates a schema that combines a type list with anyOf: the entries of type are appended to the schema's own anyOf list. The schema keeps growing on every comparison.

Reproduction

from pyagentspec.property import json_schemas_have_same_type

schema_a = {"type": ["integer", "null"], "anyOf": [{"type": "string"}]}
schema_b = {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}]}

json_schemas_have_same_type(schema_a, schema_b)
print(schema_a)
# {'type': ['integer', 'null'], 'anyOf': [{'type': 'string'}, {'type': 'integer'}, {'type': 'null'}]}
#                                        ^ two entries were appended to the caller's schema

json_schemas_have_same_type(schema_a, schema_b)
print(len(schema_a["anyOf"]))   # 5

The same happens through json_schema_is_castable_to and value_is_of_compatible_type, which are called during Flow / DataFlowEdge validation, so a Property.json_schema can change as a side effect of building a flow.

Expected behavior

Type comparison is read-only; the input schemas are left untouched.

Root cause

_normalize_json_schema_union_types in pyagentspec/src/pyagentspec/property.py uses all_types = schema.get("anyOf", []) as the accumulator of normalized types and then appends to it, so when the schema already has an anyOf list the appends go into the caller's list.

Environment

  • pyagentspec main (26.4.0.dev0), Python 3.12

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions