Skip to content

fix(utils): keep Optional fields in transform_schema - #1160

Merged
VinciGit00 merged 1 commit into
ScrapeGraphAI:mainfrom
MohammadHijjawi97:fix/transform-schema-optional-fields
Oct 6, 2026
Merged

VinciGit00 merged 1 commit into
ScrapeGraphAI:mainfrom
MohammadHijjawi97:fix/transform-schema-optional-fields

Conversation

@MohammadHijjawi97

@MohammadHijjawi97 MohammadHijjawi97 commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Pydantic v2 emits Optional[X] fields as anyOf: [X, {"type": "null"}], with no top-level type or $ref. transform_schema only handles those two keys. As a result, every Optional field is silently dropped from the simplified schema that GenerateCodeNode, PromptRefinerNode and ReasoningNode pass to the LLM:

class Product(BaseModel):
    title: str
    price: Optional[float] = None

transform_schema(Product.model_json_schema())
# before: {'title': {'type': 'string', 'description': ''}}   <- price missing
# after:  {'title': {...}, 'price': {'type': 'number', 'description': ''}}

Changes

  • When a property has anyOf with exactly one non-null variant, describe it as that variant, keeping the field's own description. It then goes through the existing type / array / $ref handling, so Optional scalars, lists and nested models are all covered. Unions of several non-null types are left as they were.
  • Added tests/utils/schema_transform_test.py.

Testing

  • pytest tests/utils/schema_transform_test.py: fails on pre/beta, passes with the fix.
  • ruff check on the changed files; black --check / isort --check-only on the new test file.

Maintainer validation

  • Target changed to main at the maintainer's explicit request; the diff remains limited to the two files above.
  • Regression test: 1 passed with Pydantic 2.12.5.
  • Additional local checks passed for optional booleans, lists of nested models, nested optional integers, unchanged multi-type union behavior, and input immutability. The original bug was reproduced against main.
  • Ruff passes on both changed files; Black and isort pass on the new test.
  • make lint fails on six pre-existing unused imports in batch_generate_answer_node.py and batch_api.py, both identical to main.
  • The full test suite was not run.

Pydantic v2 emits Optional[X] fields as `anyOf: [X, {"type": "null"}]`
with no top-level `type` or `$ref`. transform_schema only handled those
two keys, so every Optional field was silently dropped from the
simplified schema that GenerateCodeNode, PromptRefinerNode and
ReasoningNode send to the LLM.

Unwrap the single non-null variant of an anyOf and describe the field
as that type, keeping the field's own description.
@VinciGit00
VinciGit00 changed the base branch from pre/beta to main October 6, 2026 08:26
@VinciGit00
VinciGit00 merged commit 9906c69 into ScrapeGraphAI:main Oct 6, 2026
1 check passed
github-actions Bot pushed a commit that referenced this pull request Oct 6, 2026
## [2.3.1](v2.3.0...v2.3.1) (2026-10-06)

### Bug Fixes

* **utils:** keep Optional fields in transform_schema ([#1160](#1160)) ([9906c69](9906c69))
@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 2.3.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants