I have a simple LWC component that shows Contacts of a selected Account, i am calling the Apex method imperatively from my JS code while passing the Account recordId.

Here is the Apex method signature :

public static List<Contact> getRelatedContacts(Id recordId)

And my JS code snippet for the imperative call :

import getRelatedContacts from '@salesforce/apex/AccountService.getRelatedContacts';
get recordId() {
    return this._recordId;
set recordId(value) {
   this._recordId = value;
   this.setAttribute('recordId', value);
console.log('In getRelatedContacts : '+typeof(this._recordId)+' | '+this._recordId); => this returns string & the recordId on the client side
            recordId: '$_recordId'
            .then(result => {
                this.relatedContacts = result;
            .catch(error => {
                this.error = error.body.message;
                console.log('Error : '+this.error);
            .finally(() => {
                this.isLoading = false; 

But i am receiving this error message on the client side:

Value provided is invalid for action parameter 'recordId' of type 'Id'

I tried to change the Apex method signature to the following, and both passing '$_recordId' or '$recordId' but with no luck :

public static List<Contact> getRelatedContacts(String recordId)

And i get the following print with a System.debug on the server side after changing the parameter type to String :

DEBUG|boatId: $_recordId or DEBUG|boatId: $recordId

Which is strange because i am using the same syntax used here

I found this document talking about the error message, but nothing about the types 'Id' and 'String'.

Please tell what i am missing and the correct way to pass a recordId to call Apex imperatively. Thank you.

  • Is getRelatedContacts inside a method? If not, it should be, and $recordId parameter is correct.
    – Raul
    Oct 23, 2020 at 9:41
  • Yes it is inside an onclick handle method
    – THEDJA
    Oct 23, 2020 at 9:52

3 Answers 3


I have few queries on your use case.

  1. Are you using your LWC component in a record context ?

    If yes : Then the recordId is automatically set, the attribute should have @api decorator. And your implementation should work, the syntax is correct

    If No : Which means you are setting the value of the recordId, to be sent to your apex. In this case the standard attribute $recordId will not be set, since this is not a record context. Use the following syntax :

         recordId: this.recordId
  • Yes, i tried that already and it worked. So the syntax $recordId works only in a record context ? because there is no details about that in the documentation [link](developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.apex)
    – THEDJA
    Oct 23, 2020 at 11:19
  • Yes, recordId will only get set sutomatically in a record context. Refer the following link developer.salesforce.com/docs/component-library/documentation/… Oct 23, 2020 at 11:23
  • I know that, i meant the syntax with the dollar sign '$parameter' not only for a recordId, it only works in a record context for an imperative Apex call ?
    – THEDJA
    Oct 23, 2020 at 11:26

Wires use '$recordId', imperative calls use this.recordId

    recordId: this.recordId

If you want to use '$recordId' you need to mark apex method as cacheable=true

Apex: @AuraEnabled(cacheable=true) public static getObjs(Id recordId){ return [SELECT Id FROM obj WHERE Id = :recordId]; }


@wire(getObjs, {recordId : '$recordId'}) fetchResult({data, error}){ if({data}){ doSomething(); }else if({error}){ handleError(); } }

Calling Apex imperatively: @AuraEnabled public static getObjs(Id recordId){ return [SELECT Id FROM obj WHERE Id = :recordId]; }

getObjs({recordId : this.recordId}) .then({data} => { doSomething(); }) .catch({error} => { handleError(); })

You must log in to answer this question.

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