Skip to content

32561 POC: Decode error objects into user-friendly messages (DO NOT MERGE)#841

Open
severinbeauvais wants to merge 1 commit intobcgov:mainfrom
severinbeauvais:32561
Open

32561 POC: Decode error objects into user-friendly messages (DO NOT MERGE)#841
severinbeauvais wants to merge 1 commit intobcgov:mainfrom
severinbeauvais:32561

Conversation

@severinbeauvais
Copy link
Collaborator

@severinbeauvais severinbeauvais commented Feb 25, 2026

Issue #: bcgov/entity#32561

Description of changes:

  • on HTTP 422 or 400, decode each error object
  • small tweak to SaveErrorDialog text
  • created mixin with error messages structure and utlities to decode error objects into user-friendly strings

NOTE: This proof of concept is only implemented for Incorporation Applications thus far.

NOTE: To test, you need some bad data. Since the UI won't let you enter bad data, you can modify the filing JSON in the db then resume the filing and try to submit it with this code. (I corrupted the data locally while developing.)

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the bcrs-entities-create-ui license (Apache 2.0).

Copilot AI review requested due to automatic review settings February 25, 2026 22:40
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new error-decoding mixin and wires it into the app’s save-error handling so that HTTP 400/422 API error objects can be converted into more user-friendly strings for display in the Save Error dialog.

Changes:

  • Added ErrorMessageMixin with a path-based lookup table and a decodeErrorMessage() helper.
  • Updated App.vue to use the new mixin and decode errors for HTTP 400/422 before showing the save error dialog.
  • Updated Save Error dialog copy to instruct users to correct data and resubmit.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/mixins/index.ts Exports the new ErrorMessageMixin for use across the app.
src/mixins/error-message-mixin.ts Implements path-to-message mapping and error decoding logic.
src/dialogs/SaveErrorDialog.vue Updates the error dialog text shown to users.
src/App.vue Integrates the mixin and decodes 400/422 errors for display in the dialog.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +559 to +564
// on HTTP 400 or 422, decode error messages for display in dialog
if ([StatusCodes.BAD_REQUEST, StatusCodes.UNPROCESSABLE_ENTITY].includes(error?.response?.status)) {
this.saveErrors.forEach(err => {
err.error = this.decodeErrorMessage(err, filing)
})
}
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

New behavior is introduced here (decoding 400/422 API errors into user-friendly strings) but there are no unit tests covering it. Since the repo already has comprehensive unit tests for App/dialog error flows, consider adding tests that exercise the save-error-event handler for both 400 and 422 responses (including schema errors with context[].jsonPath and non-schema errors with path) and assert that the dialog receives the decoded messages.

Copilot uses AI. Check for mistakes.
Comment on lines +151 to +156
static getByPath (path: string): any {
return path
.replace(/\[(\w+)\]/g, '.$1') // convert [0] → .0
.split('.')
.reduce((o, key) => (o ? o[key] : undefined), ErrorMessageMixin.errorMessages)
}
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

getByPath() assumes path is always a non-empty string and immediately calls replace()/split(). However decodeErrorMessage() can pass undefined when err.context[0].jsonPath or err.path is missing, which will throw at runtime and prevent the save error dialog from rendering. Consider making getByPath(path?: string) return undefined when path is falsy and/or adding a fallback path string in decodeErrorMessage() when the error object lacks a path.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

@severinbeauvais severinbeauvais Feb 25, 2026

Choose a reason for hiding this comment

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

Yes, this needs to be fixed in a future commit.

Comment on lines +555 to +557
this.saveErrors = error?.response?.data?.rootCause?.errors || []
this.saveWarnings = error?.response?.data?.rootCause?.warnings || []
const filing = error?.response?.data?.rootCause?.filing || {}
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

The save error handler now reads errors/warnings only from error.response.data.rootCause. If the backend (or an upstream gateway) returns the previous shape (error.response.data.errors / warnings) this will result in an empty saveErrors array and the dialog will fall back to a generic message. To avoid a regression, consider supporting both shapes (eg, use rootCause when present, otherwise fall back to data.errors/data.warnings).

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

If the API GW is changed and the error reponse changes, this isn't the only place to fix, so that can be a global exercise and I'd prefer to leave this code as-is for now.

this.setHaveChanges(false)
this.paymentErrorDialog = true
} else {
console.log('Save error =', error) // eslint-disable-line no-console
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The error was already logged previously; there's no need for a second log.

isFutureEffective: 'Error in header object',
name: 'Error in header object',
priority: 'Error in header object',
waiveFees: 'Error in header object'
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This duplication could probably be simplified if we use a different mapping algorithm.

A different mapping algorithm could also handle the "nth" element of various arrays (and maybe even include special handling to incorporation the name of the party/share class/series).

@severinbeauvais severinbeauvais changed the title 32561 Decode error objects into user-friendly messages (DO NOT MERGE) 32561 POC: Decode error objects into user-friendly messages (DO NOT MERGE) Feb 26, 2026
- small tweak to save error dialog text
- created mixin with error messages structure and utlities to decode error objects into user-friendly strings
* FUTURE: identify party by name (from filing)
* FUTURE: identify share class/series by name (from filing)
*/
static errorMessages = {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@janisrogers Here's the structure to map the "path" to the error message.

LMK what to update :)

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