fix: response validation returns 500 instead of 422 for nested schemas#1683
Conversation
elysiajs#1659) When response validation fails on complex nested schemas (Tuples, Unions with Objects), the dynamic handler (aot: false) was returning 500 Internal Server Error instead of 422 Validation Error. Root cause: exact-mirror's Clean() function generates code that directly accesses nested properties without null checks. When called on invalid data (e.g., ver: null instead of ver: {s: '', m: null}), it throws a TypeError. Fix: Wrap Clean() calls in try-catch in dynamic-handle.ts, consistent with how compose.ts (AOT mode) already handles this. - Invalid nested response now returns 422 with proper error details - Error includes path (/items/1/1/file/ver) and message (Expected object) - Valid responses still return 200 as expected - Both aot:true and aot:false now behave consistently Closes elysiajs#1659
WalkthroughThis pull request adds defensive error handling around response validation Clean operations in the dynamic handler, wrapping them in try/catch blocks to gracefully handle Clean failures without cascading crashes. Additionally, a new test suite validates nested response schemas to ensure proper 422 validation errors for nested data mismatches. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
commit: |
Summary
Fixes #1659
When response validation fails on complex nested schemas (Tuples, Unions with Objects), the dynamic handler (
aot: false) was returning 500 Internal Server Error instead of 422 Validation Error.Root Cause
exact-mirror'sClean()function generates code that directly accesses nested properties without null checks. For example, it generates:When called on invalid data (e.g.,
ver: nullinstead ofver: {s: '', m: null}), it throws aTypeError: null is not an object.Solution
Wrap
Clean()calls in try-catch indynamic-handle.ts, consistent with howcompose.ts(AOT mode) already handles this:Now
dynamic-handle.tsdoes the same, making both modes consistent.Changes
src/dynamic-handle.ts: WrapClean()calls in try-catch blockstest/validator/response-validation-nested.test.ts: Add regression testsTest Results
aot:falseinvalid nested responseaot:trueinvalid nested responseaot:falsevalid responseaot:truevalid responseError Response Example
Now returns proper validation error with path and message:
{ "type": "validation", "on": "response", "property": "/items/1/1/file/ver", "message": "Expected object", "errors": [...] }Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.