chore: add defensive error type checking for yup validationError handling#1001
Conversation
|
|
Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com>
Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com>
Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com>
Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com>
Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR hardens checkExchangePolicy error handling to avoid unsafe access to Yup ValidationError.inner, and updates fixtures/tests to cover unsupported metadata types.
Changes:
- Added an
extractValidationErrorshelper to defensively read Yup validation errors. - Updated
checkExchangePolicyto use the helper for both base offer validation and bundle item validation. - Adjusted test fixtures and added a new test case/fixture for unsupported
metadata.type.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/core-sdk/src/offers/checkExchangePolicy.ts | Adds the defensive extraction helper and wires it into both validation catch paths. |
| packages/core-sdk/tests/check-exchange-policy.test.ts | Adds unsupported-metadata test and updates expectations for existing fixtures. |
| packages/core-sdk/tests/exchangePolicy/examples/invalidOffer6.json | Adds a new fixture used to validate unsupported metadata.type handling. |
| packages/core-sdk/tests/exchangePolicy/examples/invalidOffer2.json | Adjusts fixture metadata type to remain within supported schemas for “all errors” test. |
| packages/react-kit/src/components/offerPolicy/OfferPolicyDetails.tsx | Minor formatting change to the .find(...) predicate. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return { | ||
| message: "message" in e ? String(e.message) : "", | ||
| path: "path" in e ? String(e.path) : "", | ||
| value: "value" in e ? e.value : undefined |
There was a problem hiding this comment.
extractValidationErrors can return entries with path/message set to "undefined" (or "[object Object]") because it coerces any existing property via String(...), even when the value isn’t a string (or is undefined). This can lead to confusing paths/messages and make downstream path matching unreliable. Consider guarding with typeof e.path === "string" / typeof e.message === "string" (or e.path != null) and otherwise using an empty string or a generic message.
| return { | |
| message: "message" in e ? String(e.message) : "", | |
| path: "path" in e ? String(e.path) : "", | |
| value: "value" in e ? e.value : undefined | |
| const err = e as { message?: unknown; path?: unknown; value?: unknown }; | |
| return { | |
| message: typeof err.message === "string" ? err.message : "", | |
| path: typeof err.path === "string" ? err.path : "", | |
| value: "value" in err ? err.value : undefined |
| } catch (e) { | ||
| result = { | ||
| isValid: false, | ||
| errors: isValidationErrorWithInner(e) | ||
| ? e.inner.map((error) => { | ||
| return { ...error }; | ||
| }) | ||
| : [ | ||
| { | ||
| message: | ||
| e instanceof Error ? e.message : "Validation failed with unknown error", | ||
| path: "", | ||
| value: undefined | ||
| } | ||
| ] | ||
| errors: extractValidationErrors(e) | ||
| }; |
There was a problem hiding this comment.
In the base schema catch, errors is now set to extractValidationErrors(e). If the thrown error isn’t a Yup ValidationError (or has an empty/missing inner array), this will produce isValid: false with errors: [], which can mask failures and can be misinterpreted by consumers (e.g., UI logic that checks for specific error paths). Consider adding a fallback so that when no validation errors are extracted you still return a single error with a useful message (e.g., from e instanceof Error ? e.message : ...).
| } | ||
| ] | ||
| ); | ||
| result.errors = result.errors.concat(extractValidationErrors(e)); |
There was a problem hiding this comment.
Same issue in the bundle item validation catch: concatenating extractValidationErrors(e) can silently add no errors when a non-Yup error is thrown (or inner is empty), leaving result.isValid = false without any corresponding error details for that item. Consider using the same fallback behavior here as in the base validation path.
| result.errors = result.errors.concat(extractValidationErrors(e)); | |
| const itemErrors = extractValidationErrors(e); | |
| if (itemErrors.length > 0) { | |
| result.errors = result.errors.concat(itemErrors); | |
| } else { | |
| result.errors = result.errors.concat({ | |
| message: | |
| e instanceof Error | |
| ? e.message | |
| : "Unknown bundle item validation error.", | |
| path: "metadata.items", | |
| value: item | |
| }); | |
| } |
13a7cae
into
998-check-exchangepolicy-for-bundle
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## 998-check-exchangepolicy-for-bundle #1001 +/- ##
======================================================================
Coverage ? 90.96%
======================================================================
Files ? 176
Lines ? 7236
Branches ? 1346
======================================================================
Hits ? 6582
Misses ? 654
Partials ? 0
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
* feat: adapt check exchange policy for bundle offers * fix exchangePolicy name/version/returnPeriod in OfferPolicyDetails when bundle offer * Update packages/react-kit/src/hooks/useCheckExchangePolicy.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/core-sdk/src/offers/checkExchangePolicy.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/core-sdk/src/offers/checkExchangePolicy.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * copilot pr remarks * Update packages/react-kit/src/components/offerPolicy/OfferPolicyDetails.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/react-kit/src/hooks/useCheckExchangePolicy.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * copilot pr remarks * copilot pr remarks * copilot pr remarks * Update packages/core-sdk/src/offers/checkExchangePolicy.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/core-sdk/src/offers/checkExchangePolicy.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/react-kit/src/components/offerPolicy/OfferPolicyDetails.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update data/exchangePolicies/exchangePolicyRules.template.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/core-sdk/src/offers/checkExchangePolicy.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Add type guard for Yup ValidationError before accessing inner property (#1000) * Initial plan * Add type checking for Yup ValidationError before accessing inner property Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com> * Fix spacing in function call Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com> * chore: add defensive error type checking for yup validationError handling (#1001) * Initial plan * Add error type checking for Yup ValidationError handling Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com> * Refactor: extract error validation logic into helper function Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com> * Improve error property extraction to be more explicit Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com> * Improve type safety in error extraction helper Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com> * Add comprehensive JSDoc documentation for error extraction helper Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com> * fix lint * fix test --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com> Co-authored-by: Ludovic Levalleux <levalleux_ludo@hotmail.com> * copilot pr remarks * some additional fixes * fix render contractual agreement for bundle offer --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: levalleux-ludo <7184124+levalleux-ludo@users.noreply.github.com>
The
checkExchangePolicyfunction accessede.innerwithout verifying the error type, causing potential runtime failures when non-Yup errors are thrown.Changes
Added
extractValidationErrorshelper - Validates error object structure before accessinginnerproperty:innerarraymessage,path, andvalueproperties with type guardsApplied to both validation paths - Base validation (line 135) and bundle item validation (line 166) now use the helper
Type-safe implementation - Uses TypeScript type guards instead of
any, properly handlesunknownerror typesExample
The helper returns an empty errors array for non-Yup errors rather than throwing.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.