4

I have a record which I'm updating via the UpdateRecord method from LWC, using Toast events to display success or error messages, which all works fine. What I'm not getting though, when there's a validation error, is the error message from the validation rule. I'm getting a generic error message which is not much good as it doesn't tell me what's wrong.

  updateRecord(record)
  .then(() => {
    this.dispatchEvent(
      new ShowToastEvent({
        title: "Success",
        message: "Record has been " + this.resultmessage,
        variant: "success"
      })
    );
  })
  .catch((error) => {
    this.dispatchEvent(
      new ShowToastEvent({
        title: "Error on update",
        message: error.body.message,
        variant: "error"
      })
    );
  });

Instead of seeing the Validation Rule message, I get this: enter image description here What do I need to do to display the Validation Rule error?

UPDATE I've tried displaying the error by using this instead:

   .catch((error) => {
    this.dispatchEvent(
      new ShowToastEvent({
        title: "Error on update",
        message: error.body.output.errors[0].message,
        variant: "error",
        mode: "sticky"
      })
    );

but this returns a long ugly error:

MyTrigger: execution of AfterUpdate caused by: MyTriggerHandler.CustomException: This account requires XYZ to be done before approval. Class.MyTriggerHandler: line 448, column 1 Class.MyTriggerHandler: line 151, column 1 Class.TriggerDispatcher.Run: line 35, column 1 Trigger.MyTrigger: line 11, column 1

I went back into the class and created a custom Exception:

public class CustomException extends Exception {}
...
try {
  update accToUpdate;
} catch (DMLException e) {
  string errorMessage = e.getDmlMessage(0) == null
    ? e.getMessage()
    : e.getDmlMessage(0);

  system.debug('####catch DML Exception errorMessage: ' + errorMessage);
  system.debug('####catch DML Exception e.getDmlStatusCode: ' +        e.getDmlStatusCode(0));
  throw new CustomException(errorMessage);
}

In my debug log the debug statement shows errorMessage to be just the message (ie the 'This account requires XYZ to be done before approval.') without the class name and line numbers, so I know it goes in there and debug stops at that point after the throw. When I run this from my LWC, however, it still just displays the original error, not my custom one.

I've also tried changing the throw to AuraHandledException, but it still doesn't display just the custom message. All that changes is instead of in the long ugly error message it saying CustomException, it says AuraHandledException.

What do I need to do?

7 Answers 7

3

if you see the error message in console, error.body.message is having a generic message:- An error occurred while trying to update the record. Please try again as value.

You need to fetch the error message from the below json structure:-

error.body.output.errors[0].errorCode + error.body.output.errors[0].message

so the working code would be like:-

this.dispatchEvent(
      new ShowToastEvent({
        title: "Error on update",
        message: error.body.output.errors[0].errorCode + '- '+ error.body.output.errors[0].message,
        variant: "error"
      })
    );

enter image description here

4
  • This gives me the validation error yes, but I also get everything else with it, which is really user-unfriendly (CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY - MyTrigger: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id xxxxxxxxxxxxxx; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Validation error on field xyz.: [] Class.MyTriggerHandler.updateAccounts: line 423, column 1 Class.MyTriggerHandler.afterUpdate: line 144, column 1 External entry point Class.TriggerDispatcher.Run: line 35, column 1 Trigger.MyTrigger: line 11, column 1).
    – Irene
    Jul 14, 2020 at 5:10
  • From what you posted it looks like it should only display the errorCode and message part, but it's not (unless that IS the message?). The validation is fired from within the Apex trigger code which updates a lookup object from this main object, so the validation rule is from another object.
    – Irene
    Jul 14, 2020 at 5:16
  • Yes, I have just shown the capabilities. You can decide what you needs to show on the screen Jul 14, 2020 at 7:24
  • I'm struggling with adding logic to the ShowToastEvent though (to extract the actual error message I want - the 2nd one from the validation rule), so am not exactly sure how to do this yet - any ideas?
    – Irene
    Jul 15, 2020 at 2:11
2

Don't know if anyone is still looking for answers and help but I just came across the same issue and was able to solve it with the following. If you place this within the catch error it will display any & all errors returned from Salesforce.

// Error Handling
var errors = error.body.output.errors;
var fieldErrors = error.body.output.fieldErrors;

console.log('Errors: ');
console.log(errors);
console.log('Field Errors: ');
console.log(fieldErrors);
console.log('Generic Errors: ' + error.body.message);

if (error.body.output.errors != null) {
    console.log('Displaying Errors')
    // Loop & Display Errors
    for (let index = 0; index < error.body.output.errors.length; index++) {
        console.log('Displaying Errors');
        this.dispatchEvent(
            new ShowToastEvent({
                title: "Error on update",
                message: error.body.output.errors[index].errorCode + '- ' + error.body.output.errors[index].message,
                variant: "error"
            })
        );
    }
}
if (error.body.output.fieldErrors != null) {
    console.log('Displaying Field Errors');
    for (var prop in fieldErrors) {
        console.log(Object.keys(fieldErrors));
        var val = Object.values(fieldErrors);
        console.log(val[0][0]["message"]);
        this.dispatchEvent(
            new ShowToastEvent({
                title: 'Error Updating record',
                message: val[0][0]["message"],
                variant: 'error'
            })
        );
    }
} else {
    console.log('Displaying Generic Errors')
    this.dispatchEvent(
        new ShowToastEvent({
            title: 'Error Updating record',
            message: error.body.message,
            variant: 'error'
        })
    );
}
console.error('Error Updating Information');
console.error(error);
// End of Error Handling

This is a rough first pass and can be refined a bit. It also has a lot of extra baggage - mainly logging.

Hope this helps

1
  • 1
    should work just fine, just added an additional approach using regex
    – GirishP
    Feb 2, 2021 at 2:10
1

The error.body.message give the generic body message, so to get validation rule error message you need to use the message from fieldErrors

    this.dispatchEvent(
      new ShowToastEvent({
        title: "Error on update",
        message: emessage: error.body.output.fieldErrors.Name[0].message,
        variant: "error"
      })
    );

And you should handle the displaying of other messages not from validation rules.

1
  • I get errors if I copy your code? Should the 'emessage: ' be in there? If I remove that and run it I also get an error ( [Cannot read property '0' of undefined])
    – Irene
    Jul 14, 2020 at 5:02
0

you could do regex to get the "message" attribute and parse it accordingly. this will be generic enough to handle standard messages which generally come in a "message" tag. ex-

  1. JSON string of validation rule-

"{"status":400,"body":{"message":"An error occurred while trying to update the record. Please try again.","statusCode":400,"enhancedErrorType":"RecordError","output":{"errors":[],"fieldErrors":{"DateOfBirth__c":[{"constituentField":null,"duplicateRecordError":null,"errorCode":"FIELD_CUSTOM_VALIDATION_EXCEPTION","field":"DateOfBirth__c","fieldLabel":"Date Of Birth","message":"Customer cannot be a minor. Minimum age must be 18 years."}]}}},"headers":{}}"

  1. Regex (?<="message":")(.*?)(?=")

output The parsed text between " and " just after "message":" in the actual JSON string enter image description here

for all your custom errors from class/apex triggers etc, a standard could be followed to have message/data coming from the apex in a wrapper with the message attribute

public class LWCResponse {
@AuraEnabled
public string status;
@AuraEnabled
public string message;
@AuraEnabled
public object data;
@AuraEnabled
public Integer count;
}
0

The answers so far have given some basic strategies for correctly handling Lightning Web Component server errors, but below is the function from LWC recipes updated to handle Apex server errors (including field validations), so you don't just get the generic "Server Error" issue when there's an Apex exception.

// Parse Apex errors from server calls
const reduceErrors = (errors) => {
    if (!Array.isArray(errors)) {
        errors = [errors];
    }
    return (
        errors
            // Remove null/undefined items
            .filter((error) => !!error)
            // Extract an error message
            .map((error) => {
                // UI API read errors
                if (Array.isArray(error.body)) {
                    return error.body.map((e) => e.message);
                }
                // UI API DML, Apex and network errors
                if (error.body) {
                    let bodyMessage = [];
                    // top-level error. there can be only one
                    if (error.body.message) {
                        bodyMessage.push(error.body.message);
                    }
                    // page-level errors (validation rules, etc)
                    if (error.body.pageErrors) {
                        error.body.pageErrors.forEach(pageError => {
                            bodyMessage.push(pageError.message);
                        });
                    }
                    if (error.body.fieldErrors) {
                        // field specific errors--we'll say what the field is
                        Object.keys(error.body.fieldErrors).forEach(fieldName => {
                            // each field could have multiple errors
                            error.body.fieldErrors[fieldName].forEach(fieldError => {
                                bodyMessage.push("Field Error on " + fieldName + " : " + fieldError.message);
                            });
                        });
                    }
                    if (bodyMessage.length > 0) {
                        return bodyMessage.join("; ");
                    }
                }
                // JS errors
                if (typeof error.message === 'string') {
                    return error.message;
                }
                // Unknown error shape so try HTTP status text
                return error.statusText;
            })
            // Flatten
            .reduce((prev, curr) => prev.concat(curr), [])
            // Remove empty strings
            .filter((message) => !!message)
            .join('\n')
    );
};
0

Step # 1:

<lightning-record-edit-form object-api-name="Object_name" onsuccess={handleServiceUpdate} oncancel={handelClose} onerror={handleError}>

add onerror tag on editform.html file.

Step # 2: Add the following code in your JS file

handleError(event) {
    console.log(event.detail.detail);  // check the message on console
          
    this.showToast('Error', event.detail.detail, 'Errorr');
}

showToast(theTitle, theMessage, theVariant) {
    const event = new ShowToastEvent({
        title: theTitle,
        message: theMessage,
        variant: theVariant
    });
    this.dispatchEvent(event);
}

This will work if you have added 'validation rule' with message.

0

Adding as a follow on to @Klecool's answer above as it's not possible to format code in a comment.

If you temporarily add alert(JSON.stringify(error)); into your js you can see the structure of the error object.

@Klecool's answer works if the Validation Rule error is on a field.

If it's a page level error, then this shows the error:

          this.dispatchEvent(
              new ShowToastEvent({
                title: "Error deleting record",
                message: error.body.pageErrors[0].message,
                variant: "error",
              }),
          );

Note that both of these solutions show only the first error, even though there could be more.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .