Skip to content

Add schema path context to error messages#2786

Merged
koxudaxi merged 1 commit intomainfrom
feature/improve-error-messages-with-schema-path
Dec 24, 2025
Merged

Add schema path context to error messages#2786
koxudaxi merged 1 commit intomainfrom
feature/improve-error-messages-with-schema-path

Conversation

@koxudaxi
Copy link
Copy Markdown
Owner

@koxudaxi koxudaxi commented Dec 24, 2025

Fixes: #1330

Summary by CodeRabbit

  • Bug Fixes
    • Improved error messages when schema parsing fails by including the schema path location, simplifying debugging and error identification.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 24, 2025

📝 Walkthrough

Walkthrough

A new SchemaParseError exception class is introduced with path and original error context, then integrated into the JSON schema parser to capture and report the schema location where parsing failures occur. Tests validate the error message formatting and attribute preservation.

Changes

Cohort / File(s) Summary
Exception class definition
src/datamodel_code_generator/__init__.py
New SchemaParseError(Error) class with path and original_error attributes; formats error messages to include schema path context when available; exported in __all__.
Parser integration
src/datamodel_code_generator/parser/jsonschema.py
Added _validate_schema_object() helper method that wraps schema object validation and converts exceptions to SchemaParseError with path context; imports and uses the new exception type.
Test coverage
tests/main/test_main_general.py
Four new tests validating SchemaParseError behavior: path inclusion, nested path handling, attribute preservation, and message formatting without path.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A path through the schema maze so deep,
With breadcrumbs of context where errors sleep,
No more blind guessing through lines of nine-thousand,
The parser now whispers where trouble was found—ish! 🌙

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding schema path context to error messages to improve debugging.
Linked Issues check ✅ Passed The PR implements the core requirement from issue #1330: showing schema path context in error messages. SchemaParseError class captures path and original_error, and _validate_schema_object propagates this context during parsing.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing schema path context in error messages. No unrelated modifications were detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/improve-error-messages-with-schema-path

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Dec 24, 2025

CodSpeed Performance Report

Merging #2786 will not alter performance

Comparing feature/improve-error-messages-with-schema-path (730bc1f) with main (a46ceb8)

Summary

✅ 73 untouched
⏩ 10 skipped1

Footnotes

  1. 10 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
tests/main/test_main_general.py (1)

477-552: New SchemaParseError tests cover key behaviors

The four tests collectively verify:

  • Integration with generate() for both flat and nested schemas (including $defs/MyModel path),
  • Preservation of original_error and path,
  • Message formatting when path is omitted.

They are focused, resilient (regex-based), and exercise the intended API surface well.

If you want slightly stronger guarantees, you could also assert on exc_info.value.path contents in the nested-path test (e.g., that it ends with ["#/$defs", "MyModel"]), but the current coverage is already solid.

src/datamodel_code_generator/__init__.py (1)

393-414: SchemaParseError design and export look correct

  • The class cleanly extends Error, preserves the original exception via original_error, and adds structured path information while formatting a human-readable message.
  • Defaulting path to [] and formatting only when non-empty matches the tests’ expectations (both with and without path).
  • Adding "SchemaParseError" to __all__ makes the type publicly consumable, which is consistent with how it’s used in tests and in the JSON Schema parser.

If you later need to distinguish the raw message from the path-augmented one, consider storing the unformatted message in a separate attribute (e.g., base_message), but it’s not necessary for the current use cases.

Also applies to: 1005-1025

src/datamodel_code_generator/parser/jsonschema.py (1)

24-40: Centralized schema-object validation with SchemaParseError is well-structured

  • Importing SchemaParseError here and introducing _validate_schema_object() gives a single, consistent place to wrap low-level validation failures into a richer error that includes path and original_error.
  • The except SchemaParseError: raise clause avoids double-wrapping if future callers already raise that type, while the broad except Exception as e correctly captures any validation/runtime issues from model_validate.
  • Using message=f"{type(e).__name__}: {e}" preserves the original exception type in the human-facing message, while the underlying exception remains available via original_error for advanced consumers.

You might later consider also routing other internal model_validate(self.SCHEMA_OBJECT_TYPE, ...) call sites (e.g., in _load_ref_schema_object or merge helpers) through _validate_schema_object so that all schema-object construction failures benefit from path-aware SchemaParseError, but the current scope is already an improvement aligned with the PR goal.

Also applies to: 3109-3134

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a46ceb8 and 730bc1f.

📒 Files selected for processing (3)
  • src/datamodel_code_generator/__init__.py
  • src/datamodel_code_generator/parser/jsonschema.py
  • tests/main/test_main_general.py
🧰 Additional context used
🧬 Code graph analysis (2)
src/datamodel_code_generator/parser/jsonschema.py (3)
src/datamodel_code_generator/__init__.py (1)
  • SchemaParseError (393-413)
src/datamodel_code_generator/util.py (1)
  • model_validate (201-205)
src/datamodel_code_generator/__main__.py (1)
  • parse_obj (126-128)
tests/main/test_main_general.py (1)
src/datamodel_code_generator/__init__.py (1)
  • SchemaParseError (393-413)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: py312-pydantic1 on Ubuntu
  • GitHub Check: 3.12 on Ubuntu
  • GitHub Check: py312-black24 on Ubuntu
  • GitHub Check: py312-isort7 on Ubuntu
  • GitHub Check: py312-black22 on Ubuntu
  • GitHub Check: py312-isort6 on Ubuntu
  • GitHub Check: 3.10 on macOS
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.12 on macOS
  • GitHub Check: 3.11 on Windows
  • GitHub Check: py312-isort5 on Ubuntu
  • GitHub Check: 3.11 on macOS
  • GitHub Check: 3.13 on macOS
  • GitHub Check: 3.10 on Ubuntu
  • GitHub Check: 3.12 on Windows
  • GitHub Check: 3.11 on Ubuntu
  • GitHub Check: 3.14 on Windows
  • GitHub Check: 3.13 on Windows
  • GitHub Check: Analyze (python)
  • GitHub Check: benchmarks
🔇 Additional comments (2)
tests/main/test_main_general.py (1)

11-20: Public import of SchemaParseError is appropriate

Exposing SchemaParseError at the top-level for tests (and users) matches its role as a first-class, library-defined error type and aligns with the new test usage.

src/datamodel_code_generator/parser/jsonschema.py (1)

3278-3299: Path propagation into SchemaParseError from file roots, definitions, and JSON pointers

  • Validating raw with _validate_schema_object(raw, path_parts or ["#"]) ensures root-level schema failures now report either the source path or a synthetic "#" anchor.
  • For definitions, constructing definition_path = [*path_parts, schema_path, key] and using it for both _validate_schema_object and parse_id gives precise paths like .../#/$defs/MyModel, which matches the new nested-path test and improves $id bookkeeping.
  • For targeted object paths and reserved refs, passing path derived from the JSON pointer (reserved_path.split("/")) yields intuitive messages such as #/components/schemas/Foo, tying errors directly to the pointer being resolved.

Because parse_id now receives definition_path instead of just path_parts, the stored $id → path mapping in the model resolver will change slightly for schemas under #/definitions / #/$defs. This should be an improvement, but please verify any existing tests or fixtures that rely on $id-based resolution (especially multi-file or external $id references) still behave as expected.

Also applies to: 3318-3319

@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 24, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.47%. Comparing base (a46ceb8) to head (730bc1f).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2786   +/-   ##
=======================================
  Coverage   99.47%   99.47%           
=======================================
  Files          88       88           
  Lines       13213    13256   +43     
  Branches     1556     1557    +1     
=======================================
+ Hits        13144    13187   +43     
  Misses         36       36           
  Partials       33       33           
Flag Coverage Δ
unittests 99.47% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@koxudaxi koxudaxi merged commit 5cceb4f into main Dec 24, 2025
38 checks passed
@koxudaxi koxudaxi deleted the feature/improve-error-messages-with-schema-path branch December 24, 2025 17:33
@github-actions
Copy link
Copy Markdown
Contributor

Breaking Change Analysis

Result: Breaking changes detected

Reasoning: This PR changes the exception type raised when schema parsing fails. Previously, Pydantic's ValidationError would propagate directly from model_validate() calls. Now, these errors are caught and re-raised as SchemaParseError with additional path context. While this improves error messages by including schema path information, it changes the exception type that users might be catching. Users who specifically catch pydantic.ValidationError for schema validation errors will need to update their exception handling to catch SchemaParseError instead.

Content for Release Notes

Error Handling Changes

  • Schema validation errors now raise SchemaParseError instead of Pydantic ValidationError - When parsing invalid schema data (e.g., "minimum": "not_a_number"), the library now raises SchemaParseError instead of passing through Pydantic's ValidationError. Users who were specifically catching pydantic.ValidationError for schema validation failures should update their code to catch SchemaParseError instead. The original error is preserved in the original_error attribute. Code catching the base Error class or Exception is unaffected. (Add schema path context to error messages #2786)

This analysis was performed by Claude Code Action

koxudaxi added a commit that referenced this pull request Dec 25, 2025
* Add --collapse-root-models-name-strategy option

* docs: update CLI reference documentation and prompt data

🤖 Generated by GitHub Actions

* Add pragma no cover for defensive edge cases

* Achieve 100% diff coverage for collapse-root-models-name-strategy

* Use cast instead of type ignore comment

* Remove line comments from collapse-root-models implementation

* Add complex e2e tests for collapse-root-models-name-strategy

* Update reference metadata when renaming in parent strategy

* Refactor collapse-root-models tests to use parameterization for v1/v2

* Add schema path context to error messages (#2786)

* Return str or dict when output=None in generate() (#2787)

* Add --http-timeout CLI option (#2788)

* Add --http-timeout CLI option for configurable HTTP request timeout

* docs: update CLI reference documentation and prompt data

🤖 Generated by GitHub Actions

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Pass schema extensions to templates (#2790)

* Pass schema extensions to templates

* Move model_base import to top of file

* Add schema extensions documentation

Document how x-* schema extensions are passed to custom templates
via the extensions variable, with examples for database model
configuration and other use cases.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* Add propertyNames and x-propertyNames support (#2789)

* Add propertyNames and x-propertyNames support

* Fix Pydantic v1 compatibility for x-propertyNames

Use the model_validate utility function from util module instead of
calling JsonSchemaObject.model_validate() directly, which only
exists in Pydantic v2.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* Add test for x-propertyNames non-dict branch coverage

Test that x-propertyNames with non-dict value (e.g., boolean) is
correctly ignored, achieving 100% diff coverage.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* Add support for additional_imports in extra-template-data JSON (#2793)

* Update zensical to 0.0.15 (#2794)

* Add --use-field-description-example option (#2792)

* Add --use-field-description-example option

* docs: update CLI reference documentation and prompt data

🤖 Generated by GitHub Actions

* Add tests for complete branch coverage of docstring property

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Fix formatting in test file

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
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.

Improve error messages to include an idea where the error occurred

1 participant