Handle Errors in Lightning Data Service

Lightning Data Service (LDS) wire adapters return an error when a resource, such as a record or an object, is inaccessible on the server.

For example, an error occurs if you pass in an invalid input to the wire adapter, such as an invalid record Id or missing required fields. An error is also returned if the record isn’t in the cache and the server is offline. Also, a resource can become inaccessible on the server when it’s deleted or has its sharing or visibility settings updated.

LWC Error Handling Best Practices

Errors in Asynchronous JavaScript 

Using the LDS wire adapters means you are working with asynchronous JavaScript, which is similar to promises. To handle errors, you typically use a try-catch block. However, the try-catch block can handle exceptions in synchronous code only. So only errors within a single transaction are caught by a try-catch block.

Consider this asynchronous code.

1connectedCallback() {
2  try {
3    console.log("first");
4    setTimeout(() => {
5      throw new Error("some error");
6      console.log("second");
7    }, 1000);
8  } catch (e) {
9    console.log(e);
10  }
11  console.log("third");
12}

The code prints first, then runs setTimeOut(), and prints third in a single transaction. The callback function is called 1 second later, as specified by the timeout delay. However, second isn’t printed since it’s not part of the first transaction.

To ensure that your error in asynchronous code is handled correctly in a try-catch block, use the try-catch block inside the callback function.

1connectedCallback() {
2  console.log("first");
3  setTimeout(() => {
4    try {
5      throw new Error("some error");
6      console.log("second");
7    } catch(e) {
8      console.log("error");
9    }
10  }, 1000);
11  console.log("third");
12}

The code prints first, then runs setTimeOut(), and prints third in a single transaction. When the callback is called 1 second later, the try-catch block handles the error and prints error correctly.

Errors in LDS Wire Adapters 

When you specify the @wire decorator and make a call out to a wire service, the wire service calls the wire adapter to fetch the data. The wire adapter fetches the data either from Salesforce servers or the LDS cache, if it’s available. The wire adapter then returns the data back to the service, which provisions the data back to your component.

We say “provisions” instead of “requests” or “fetches” because a network request isn’t involved if the data exists in the client cache.

Note

The response may throw an error during or after value provisioning. For example, the wire adapter tries to fetch the data from your Apex method and the Apex method throws an exception. This exception can occur because of a number of reasons, such as if you don’t parse a required parameter or if there’s an issue fetching from the cache.

If the value provisioning is successful, you can also encounter an error while handling the response on your component.

The lwc-recipes repo has many wire service examples. Look for components that start with lds*, such as ldsCreateRecord, or components that start with apex*, such as apexImperativeMethod.

Tip

When you wire a method to a function or a property, the error property stores the error during value provisioning. We recommend that you include the else if block to handle errors on your wire functions. Wire a method to a function with error handling like this.

1@wire(getApexMethod)
2wiredContacts({ error, data }) {
3  if (data) {
4    try {
5      // handle result
6    } catch(e) {
7      // error when handling result
8    }
9  } else if (error) {
10    // error with value provisioning
11  }
12}

If you wire a method to a property instead, you can handle the error by checking the yourPropertyName.error value.

You must use the data and error properties as they are hardcoded values in the API. See Wire Service Syntax.

Note

Error Response 

The FetchResponse error object is modeled after the Fetch API’s Response object. It contains the body of the response and a status code and message.

Here’s an example error response when you provide an incorrect recordId for an object.

1{
2  "status": 400,
3  "body": {
4    "message": "The \"fields\" query string parameter contained object api names that do not correspond to the api names of any of the requested record ids. The requested object api names were: [Account], while the requested records had object types: [Contact]",
5    "statusCode": 400,
6    "errorCode": "INVALID_INPUT"
7  },
8  "headers": {},
9  "ok": false,
10  "statusText": "Bad Request",
11  "errorType": "fetchResponse"
12}

Error Properties 

The error response includes these properties.

  • body (Object or Array)—The body of the response, which is defined by the underlying API.
  • ok (Boolean)—Specifies whether the response was successful or not. For an error, ok is always false and contains a status in the range 400–599.
  • status (Number)—Contains the status code of the response, for example, 404 if a resource is not found or 500 for an internal server error.
  • statusText (String)—Contains the status message corresponding to the status code, for example, NOT_FOUND for a status code of 404.

Example: Handle Errors from the getRecord Wire Adapter 

To handle errors returned by the getRecord wire adapter, you can display the error in your HTML template or handle them in JavaScript only. This example displays the error to users.

1<template>
2  <lightning-card title="Handle Error" icon-name="standard:contact">
3    <template lwc:if={error}>
4      <p>{error}</p>
5    </template>
6  </lightning-card>
7</template>

The JavaScript code checks if the error body is an array or object and returns the error message.

1import { LightningElement, api, wire, track } from "lwc";
2import { getRecord } from "lightning/uiRecordApi";
3
4const fields = [
5  // This invalid field causes @wire(getRecord) to return an error
6  "Contact.invalidField",
7];
8
9export default class WireGetRecordDynamicContact extends LightningElement {
10  @api recordId;
11
12  @track error;
13
14  @wire(getRecord, { recordId: "$recordId", fields })
15  wiredRecord({ error, data }) {
16    if (error) {
17      this.error = "Unknown error";
18      if (Array.isArray(error.body)) {
19        this.error = error.body.map((e) => e.message).join(", ");
20      } else if (typeof error.body.message === "string") {
21        this.error = error.body.message;
22      }
23      this.record = undefined;
24    } else if (data) {
25      // Process record data
26    }
27  }
28}

The lwc-recipes repo has an ldsUtils example that reduces one or more LDS errors into a string array of error messages.

Tip

Body Payload 

The body of the error response depends on the API that returns it.

  • UI API read operations, such as the getRecord wire adapter, return error.body as an array of objects.
  • UI API write operations, such as the createRecord wire adapter, return error.body as an object, often with object-level and field-level errors.
  • Apex read and write operations return error.body as an object.
  • Network errors, such as an offline error, return error.body as an object.

Before the wire fires for the first time, both data and error are undefined. The wire isn’t in an error state, it just hasn’t fired yet. See Wire Service Syntax.

Note

See Also