Skip to content

fix(serialization): preserve validation error messages when deserializing invalid components - #270

Open
fede-kamel wants to merge 1 commit into
oracle:mainfrom
fede-kamel:fix/deserializer-validation-errors
Open

fede-kamel wants to merge 1 commit into
oracle:mainfrom
fede-kamel:fix/deserializer-validation-errors

Conversation

@fede-kamel

Copy link
Copy Markdown
Member

Fixes #269.

Root cause

PydanticComponentDeserializationPlugin.deserialize collects the validation errors of a component and rebuilds a ValidationError from InitErrorDetails(type=e.type, loc=e.loc, input=()). pydantic cannot render error types such as value_error, which is what every @model_validator_with_error_accumulation validator raises, from the type alone: they need the context of the original error. ValidationError.from_exception_data therefore raised TypeError: ValueError: 'error' required in context and the real message (the unreachable end node, the input missing from the prompt, ...) was lost for every from_dict, from_json and from_yaml call on an invalid component.

Changes

  • serialization/pydanticdeserializationplugin.py: wrap the original error type and message in a PydanticCustomError when rebuilding the line errors. This preserves both for every error type without needing the original context. The partial-construction path (from_partial_dict, which returns the collected errors) is unchanged.
  • tests/serialization/test_serialization.py: regression tests covering a Flow with an unreachable EndNode through Component.from_dict, from_json, from_yaml and AgentSpecDeserializer.from_dict, and an Agent declaring an input that is not in its prompt. They assert the ValidationError carries the original message and the value_error type. All fail on main with the TypeError, pass with the fix.
  • Changelog entry under Bug fixes.

Verification

  • SKIP_LLM_TESTS=1 pytest tests --ignore=tests/adapters --ignore=tests/evaluation: 912 passed, 407 skipped (Python 3.13).
  • black, isort, flake8 (the only E501 hits are pre-existing lines) and mypy on the serialization package are clean.

@fede-kamel
fede-kamel requested a review from a team October 1, 2026 15:10
@oracle-contributor-agreement oracle-contributor-agreement Bot added the OCA Verified All contributors have signed the Oracle Contributor Agreement. label Oct 1, 2026

@fede-kamel fede-kamel left a comment •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

…zing invalid components

When a component failed validation during Component.from_dict,
from_json or from_yaml, PydanticComponentDeserializationPlugin.deserialize
rebuilt the ValidationError from the collected error type and location
only. Pydantic error types such as value_error, which is what every
@model_validator_with_error_accumulation validator raises, cannot be
rebuilt without the context of the original error, so the deserializer
crashed with "TypeError: ValueError: 'error' required in context" and
the real message, for instance the end node without incoming control
flow edge, was lost. The rebuilt line errors now wrap the original type
and message in a PydanticCustomError, which keeps the error type and the
message for every error type. The partial construction path
(build_from_partial_config, get_validation_errors) is unchanged.

Fixes oracle#269.
@fede-kamel
fede-kamel force-pushed the fix/deserializer-validation-errors branch from 3e73dd2 to 6107693 Compare October 9, 2026 19:16

@fede-kamel fede-kamel left a comment •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

This branch has not been deployed

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

Labels

OCA Verified All contributors have signed the Oracle Contributor Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deserializing an invalid component raises TypeError: ValueError: 'error' required in context instead of the validation message

1 participant