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

@wire(getRecord, ...) requires the fields property

You used `getRecord` from `lightning/uiRecordApi` without specifying which fields to fetch. LDS doesn't auto-fetch all fields like an old-school SQL `SELECT *`; you must list each field you want.

Also seen asgetRecord requires fields·@wire getRecord without fields·Required parameter fields was not provided·LDS without fields

The Lightning Data Service (LDS) getRecord adapter is field-explicit by design. It fetches exactly what you list and nothing more — for performance, security, and cache efficiency.

What's required

import { LightningElement, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';
import NAME_FIELD from '@salesforce/schema/Account.Name';
import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry';

export default class MyComp extends LightningElement {
  @api recordId;
  
  @wire(getRecord, { recordId: '$recordId', fields: [NAME_FIELD, INDUSTRY_FIELD] })
  account;
  
  get accountName() {
    return this.account?.data?.fields?.Name?.value;
  }
}

The fields property is required. Each field is imported from @salesforce/schema/<Object>.<FieldName>.

Why imports, not strings

LDS uses the @salesforce/schema/... imports to:

  1. Generate a static dependency — the build tool knows which fields the component reads, so deploys can warn if a field doesn't exist.
  2. Trigger field-rename safety — if the field gets renamed in a deploy, the import breaks at compile time.
  3. Enforce per-component field tracking — performance optimisations rely on knowing exactly what each component needs.

So you can't pass fields: ['Account.Name'] as a plain string. The platform rejects it.

What the wire returns

The wired property has a complex shape:

{
  data: {
    apiName: 'Account',
    childRelationships: {},
    eTag: 'xxx',
    fields: {
      Name: { displayValue: null, value: 'Acme Corp' },
      Industry: { displayValue: 'Technology', value: 'Tech' }
    },
    id: '0016xxx',
    lastModifiedById: '005xxx',
    lastModifiedDate: '...',
    recordTypeInfo: null,
    systemModstamp: '...'
  },
  error: undefined
}

Note the indirection: data.fields.Name.value (not just data.Name). This is so picklists can carry both value (API value) and displayValue (translated label). Dotted access:

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

A simpler alternative for read-only views

For just rendering a record, the lightning-record-view-form component handles all this for you:

<lightning-record-view-form record-id={recordId} object-api-name="Account">
  <lightning-output-field field-name="Name"></lightning-output-field>
  <lightning-output-field field-name="Industry"></lightning-output-field>
</lightning-record-view-form>

No imports, no wire, no manual field selection. The framework handles fetching, caching, and FLS.

When you need many fields

Importing 30 individual fields gets tedious. Use a LIST of strings imported via the schema namespace if you don't need static type safety:

const FIELDS = [
  'Account.Name',
  'Account.Industry',
  'Account.AnnualRevenue',
  // ...
];

This works as long as your component is module-scoped and can take a list of strings; LDS accepts both forms.

A common bug: using getRecord for write

getRecord is read-only. To update a record, use updateRecord from the same module:

import { updateRecord } from 'lightning/uiRecordApi';

await updateRecord({ fields: { Id: this.recordId, Name: 'New' } });

Don't try to mutate the wire's data and re-render — LDS won't persist that.

Related dictionary terms