6

I'm having a slightly irritating error when trying to add some of my code to a managed package. I'm sure there's something silly that I'm doing.

I have a LWC which calls two separate apex methods - one that just takes a basic parameter (a string) and one that takes a class as a parameter containing properties, arrays etc. A wrapper class essentially.

Both of these methods work absolutely fine in my dev org - the request hits the apex, apex calls out to an API, database updated, LWC redirects to the new record.

I've added this code to a managed package and installed it in a couple of different orgs. The method which just takes a single param works fine, the one that accepts a class as a parameter is bombing out, with this beautiful error message:

{"status":500,"body":{"message":"An internal server error has occurred\nError ID: 316185011-592324 (-524102090)"},"headers":{}}

I've spent quite a bit of time debugging the request in both the dev org and the package, and I believe that everything is fine code wise - the request object is populating with all of the relevant fields and to be honest, the request isn't rocket science so I believe it's something to do with the wiring between the LWC and the apex class. Again, the other method which just takes a single parameter (and is also in the same apex class) works fine including in the package.

So, here's my JS controller code:

handleCreateContact() {
    // Show spinner
    this.loaded = false;

    const evt = new ShowToastEvent({
        title: 'Create Contact',
        message: 'Sending Request',
        variant: 'info',
    });

    this.dispatchEvent(evt);
       
    console.log('Account ID: ' + this.accountId);
    console.log('Contact name: ' + this.contactName);
        
    let apexRequest = { 
                        "AccountId" : this.accountId, 
                        "ContactName" : this.contactName ,
                        "PostalStreet" : this.contactPostalStreet,
                        "PostalCity" : this.contactPostalCity,
                        "PostalState" : this.contactPostalState,
                        "PostalCode" : this.contactPostalCode,
                        "PostalCountry" : this.contactPostalCountry
    }

    console.log('*** create contact request: ' + JSON.stringify(apexRequest));

    CreateContacts({ request: apexRequest })
        .then(result => {
            const evt = new ShowToastEvent({
                title: 'Create Contact',
                message: 'Contact Created',
                variant: 'success',
            });
        
            this.dispatchEvent(evt);

            console.log('Contact ID: ' + result.SalesforceContactID);
            console.log('Result: ' + JSON.stringify(result));
    
            this[NavigationMixin.Navigate]({
                type: 'standard__recordPage',
                attributes: {
                    recordId: result.SalesforceContactID,
                    actionName: 'view'
                },
            });
        })
        .catch(error => {
            // Didn't work
            console.log('**ERRROR: ' + JSON.stringify(error));

            let errorMessage = '';

            if (error.status != undefined) {
                errorMessage = errorMessage + error.status + ': ';
            }
                    
            if (error.body.message) {
                errorMessage = errorMessage + ' - ' + error.body.message;
            }
            else if (error.body.pageErrors) {
                errorMessage =  errorMessage + error.body.pageErrors[0].statusCode + ' - ' + error.body.pageErrors[0].message;
            }

            const evt = new ShowToastEvent({
                title: 'Refresh Contacts Failed',
                message: errorMessage,
                variant: 'error',
            });

            this.dispatchEvent(evt);
        })
        .finally(() => {
            this.loaded = true;
        });
    }

My apex method (class is set to public)

@auraEnabled(cacheable=false)
    public static CreateContactResponse CreateContactAura(CreateContactRequest request)
    {
        return new xContacts().CreatexContact(request);
    }

And finally the wrapper classes:

public class CreateContactRequest
    {
        @AuraEnabled
        public Id AccountId { get; set; }

        @AuraEnabled
        public String ContactName { get; set; }

        @AuraEnabled
        public String PostalStreet { get; set; }

        @AuraEnabled
        public String PostalCity { get; set; }

        @AuraEnabled
        public String PostalState { get; set; }

        @AuraEnabled
        public String PostalCode { get; set; }

        @AuraEnabled
        public String PostalCountry { get; set; }
    }

    public class CreateContactResponse
    {
        @AuraEnabled
        public String xID { get; set; }

        @AuraEnabled
        public ID SalesforceContactID { get; set; }
    }

Given that this is only happening when the code is packaged I suspect it's something around namespacing/security/class access but thought I'd post here first to see if anyone can save me some time redeploying the package 30 times for debugging the issue!

I was wondering whether perhaps the wrapper classes and properties just need to be set to global, but I'm sure I'm missing something stupid here...

Edit: Just to add a bit more info after some investigation...

If I have a method that returns a wrapper class as above, but takes a single input parameter such as an Id then that works in both the dev org and managed package.

I've modified the apex class (different class, easier for testing) from this:

public static GetInvoiceFromDatabaseResponse GetInvoiceFromDatabaseAura(Id SfId)

to this:

public static GetInvoiceFromDatabaseResponse GetInvoiceFromDatabaseAura(testWrapperClass invoiceRequest)

with this wrapper class...

   public class testWrapperClass
    {
        @auraEnabled
        public String sfId { get; set; }
    }

And that is working in my developer org, but failing in the managed package. So apparently, the issue is specific to using a wrapper class for the input parameter of an apex method, but it's absolutely fine to return a wrapper class.

4
  • Welcome to Salesforce Stack Exchange (SFSE)! [1] I know very little about managed packages, so unless you need to prefix every class call with the namespace, I can't help. [2] FYI: When using the SE editor, to properly format code blocks you need to use three backticks: ``` (found on U.S. QWERTY keyboard to the left of the "1" on the same key as the tilde (~)) - you were using three single quotes: '''.
    – Moonpie
    Commented Feb 8, 2022 at 20:20
  • 1
    Hi Chris, I doubt you're "missing something stupid here". This might well be a Salesforce bug. If I were you, I'd stringify the "apexRequest" parameter, pass a String to the AuraEnabled method and deserializeStrict in Apex. I've had several cases in the past, where this worked more reliably than passing objects on as such. Commented Feb 10, 2022 at 12:53
  • Thanks Felix - just seems like such a manual faff around something that should just work. I've actually solved this now, so I'll add the solution...
    – Chris
    Commented Feb 11, 2022 at 12:07
  • I'm just adding this error messages that I got - 585210355-35064 (-524102090) - so that search engines can index that and others can find this post. Thanks @Chris you saved me quite a bit of time! Commented Apr 12 at 20:49

3 Answers 3

9

Just in case anyone comes across this in the future, I think I've solved this now (although now Salesforce is not allowing me to install my package at all, but that's a Salesforce issue I think. I'm sure that'll resolve itself shortly).

The problem, apparently, was that my request wrapper class was an inner class of a parent class. Strangely, this wasn't a problem for the response class which continued to function well but the fix was to take my request class out of my "controller" class and move it into its own apex class.

I typically like my request classes to be inner classes for encapsulation reasons but apparently going forward I need to always put these wrappers in a separate class, despite what my OCD traits tell me...

2
  • 1
    Dude, your own answer literally saved me hours of crazy debugging. I've stumbled across the same issue after installing my own managed package to a "real org"... using the error code I finally came to this question and your answer solved the issue: slide refactoring of code, getting rid of inner classed and tadaaa: it works! Thanks!
    – derroman
    Commented Apr 24, 2022 at 18:26
  • 1
    Ha, it's about time I "paid it forward" after all the time I've spent finding answers on here from other people. Glad I could help!
    – Chris
    Commented Apr 26, 2022 at 7:33
2

This is a known issue https://trailblazer.salesforce.com/issues_view?id=a1p3A0000001CBeQAM with NO FIX Resolution.

And there is a related Idea on IdeaExchange https://ideas.salesforce.com/s/idea/a0B8W00000GdWFxUAN/fix-nested-classes-for-auraenabled-methods-with-namespace

The only workaround is to avoid using namespaced inner classes as Lightning attribute types.

0

I hope my answer will help someone.

I had similar issue with my packaged LWC, but in my case the issue was that I was exposing the protected Custom Setting in @AuraEnabled methods. Once I created a top level wrapper class(using an inner wrapper class will produce the same issue) - the issue was resolved.

So, in short, do not use protected custom settings in your @AuraEnabled methods :) The funny thing, that exposing protected custom settings to VisualForce page does not produce any issues.

You must log in to answer this question.

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