Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
All errors
Lightning · LWC

Cannot read properties of undefined (reading 'X') — in LWC component lifecycle

Plain JavaScript TypeError, but in LWC it almost always means a `@wire` result was read in `connectedCallback` or `renderedCallback` before the wire actually returned data. The fix is to defer reads until you have data, or to use the wire's loading state explicitly.

Also seen asCannot read properties of undefined·Cannot read property of undefined·TypeError: Cannot read properties of undefined·LWC undefined

This is the JavaScript runtime telling you that you tried to read a property off undefined. In LWC the most common pattern is:

@wire(getRecord, { recordId: '$recordId', fields: ACCOUNT_FIELDS })
account;

connectedCallback() {
  this.label = this.account.data.Name;   // 💥 this.account is undefined here
}

@wire is asynchronous. The wired property doesn't exist when connectedCallback runs — it gets populated later, when the framework receives the response.

The four shapes of the bug, with fixes

1. Reading wire data in a lifecycle hook before it's loaded

Don't. Move the work into a getter that reads from this.account?.data:

@wire(getRecord, { recordId: '$recordId', fields: ACCOUNT_FIELDS })
account;

get accountName() {
  return this.account?.data?.fields?.Name?.value ?? '';
}

The template re-renders when wire data lands; the getter recomputes; the page updates. No imperative timing required.

2. Reading a deeply nested wire response without optional chaining

get website() {
  return this.account.data.fields.Website.value;     // 💥
}

Every . is a chance for undefined. Use ?. to short-circuit:

get website() {
  return this.account?.data?.fields?.Website?.value ?? '';
}

This is verbose but correct. If you find yourself writing it five times in the same component, extract a helper that takes a field name and walks the path.

3. Iterating a wire array before it returned

@wire(getAccounts) accounts;

get sortedAccounts() {
  return this.accounts.data.sort(...);   // 💥 .data is undefined initially
}

Always guard the iteration:

get sortedAccounts() {
  if (!this.accounts?.data) return [];
  return [...this.accounts.data].sort(...);
}

(And note the spread — calling .sort() directly on this.accounts.data mutates the wired array, which fights the framework. Always copy first.)

4. Reading a @api property in connectedCallback

@api properties are set by the parent after connectedCallback. If the component reads this.someApiProp in connectedCallback, it'll be undefined even if the parent eventually passes it.

Move the work to renderedCallback (which fires every render and lets you check if (this.someApiProp)) or to a setter:

@api
set recordId(value) {
  this._recordId = value;
  if (value) this.loadStuff();   // run once we actually have it
}
get recordId() {
  return this._recordId;
}

When the error is from a third-party child component

Sometimes the bug isn't in your component but in a child component that didn't handle a missing prop. Pass safe defaults from the parent template:

<c-fancy-table records={records ?? []}></c-fancy-table>

Empty arrays and empty strings beat undefined propagating downstream every time.

Related dictionary terms