function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Stéphane Bernhardt SalesForceStéphane Bernhardt SalesForce 

Trailhead - Connect to Salesforce with Server-Side Controllers - Internal error

Hi,

I'm currently working on the "Connect to Salesforce with Server-Side Controllers" module and I'm facing an error.

The error is:
Error: An internal server error has occurred
Error ID: 615929029-122427 (-1189130377)



I already:
  • Re-wrote the code from zero
  • Checked other posts on this forum
  • Checked fields security
  • Tried to remove the "with sharing" from the Apex controller
The challenge has been marked "completed" but it doesn't work :(

I did not have any issue on the previous unit, with expenses.

Please find my code below. Do you have an idea because I'm going crazy :)

Camping.cmp:
<aura:component>
    <aura:attribute name="items" type="Camping_Item__c[]"/>
    <!-- PAGE HEADER -->
    <div class="slds-page-header" role="banner">
      <div class="slds-grid">
        <div class="slds-col">
          <p class="slds-text-heading--label">Camping items</p>
          <h1 class="slds-text-heading--medium">Items</h1>
        </div>
      </div>
    </div>
    <!-- / PAGE HEADER -->
	<c:campingList items="{!v.items}"/>
</aura:component>
campingList.cmp:
<aura:component controller="CampingListController">
	<aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    <aura:attribute name="items" type="Camping_Item__c[]"/>
    <aura:attribute name="newItem" type="Camping_Item__c"
     default="{ 'sobjectType': 'Expense__c',
                    'Name': '',
                    'Price__c': 0,
                    'Quantity__c': '',
                    'Packed__c': false }"/>
    
    <!-- NEW EXPENSE FORM -->
    <div class="slds-col slds-col--padded slds-p-top--large">
  
          <div aria-labelledby="newitemform">
        
          <!-- BOXED AREA -->
          <fieldset class="slds-box slds-theme--default slds-container--small">
        
            <legend id="newItemform" class="slds-text-heading--small 
              slds-p-vertical--medium">
              Add Item
            </legend>
        
            <!-- CREATE NEW EXPENSE FORM -->
            <form class="slds-form--stacked">
        
              <div class="slds-form-element slds-is-required">
                  <div class="slds-form-element__control">
                      <ui:inputText aura:id="itemname" label="Item Name"
                          class="slds-input"
                          labelClass="slds-form-element__label"
                          value="{!v.newItem.Name}"
                          required="true"/>
                  </div>
             </div>
             <div class="slds-form-element slds-is-required">
                  <div class="slds-form-element__control">
                      <ui:inputNumber aura:id="itemprice" label="Price"
                          class="slds-input"
                          labelClass="slds-form-element__label"
                          value="{!v.newItem.Price__c}"
                          required="true"/>
        
                  </div>
              </div>
        
              <div class="slds-form-element">
                  <div class="slds-form-element__control">
                      <ui:inputNumber aura:id="itemquantity" label="Quantity"
                          class="slds-input"
                          labelClass="slds-form-element__label"
                          value="{!v.newItem.Quantity__c}"/>
                  </div>
              </div>
        
              <div class="slds-form-element">
                  <ui:inputCheckbox aura:id="itempacked" label="Packed?"
                      class="slds-checkbox"
                      labelClass="slds-form-element__label"
                      value="{!v.newItem.Packed__c}"/>
              </div>        
              <div class="slds-form-element">
                  <ui:button label="Create Item"
                      class="slds-button slds-button--brand"
                      press="{!c.clickCreateItem}"/>
              </div>
        
            </form>
            <!-- / CREATE NEW EXPENSE FORM -->
        
          </fieldset>
          <!-- / BOXED AREA -->
        
        </div>
        <!-- / CREATE NEW EXPENSE -->
    </div>    
    
    
    <div class="slds-card slds-p-top--medium">
        <header class="slds-card__header">
            <h3 class="slds-text-heading--small">Camping Items</h3>
        </header>
        
        <section class="slds-card__body">
            <div id="list" class="row">
                <aura:iteration items="{!v.items}" var="item">
                    <c:CampingItem item="{!item}"/>
                </aura:iteration>
            </div>
        </section>
    </div>

</aura:component>

CampingItem.cmp:
<aura:component >
    <aura:attribute name="item" type="Camping_Item__c"/>
    <p>Name:
        <ui:outputText value="{!v.item.Name}"/>
    </p>
    <p>Price:
        <ui:outputNumber value="{!v.item.Price__c}"/>
    </p>
    <p>Quantity:
        <ui:outputNumber value="{!v.item.Quantity__c}"/>
    </p>
    <p>Packed?:
        <ui:outputCheckbox value="{!v.item.Packed__c}"/>
    </p>
</aura:component>
CampingListController.apxc:
public with sharing class CampingListController {

    @AuraEnabled
    public static List<Camping_Item__c> getItems() {
        // Perform isAccessible() checking first, then
        return [SELECT Name, Price__c, Quantity__c, Packed__c FROM Camping_Item__c];
    }
    
    @AuraEnabled
    public static Camping_Item__c saveItem(Camping_Item__c newItem) {
        // Perform isUpdatable() checking first, then
        upsert newItem;
        return newItem;
    }
}
campingListController.js:
({
    // Load items from Salesforce
    doInit: function(component, event, helper) {
    
        // Create the action
        var action = component.get("c.getItems");
    
        // Add callback behavior for when response is received
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                component.set("v.items", response.getReturnValue());
            }
            else {
                console.log("Failed with state: " + state);
            }
        });
    
        // Send action off to be executed
        $A.enqueueAction(action);
    },
    
    clickCreateItem: function(component, event, helper) {
        if(helper.validateItemForm(component)){
            // Create the new item
            var newItem = component.get("v.newItem");
            helper.createItem(component, newItem);
        }
    }
})

campingListHelper.js:
({
    
    validateItemForm: function(component) {
        // Simplistic error checking
        var validItem = true;
    	/*
        // Name must not be blank
        var nameField = component.find("expname");
        var expname = nameField.get("v.value");
        if ($A.util.isEmpty(expname)){
            validExpense = false;
            nameField.set("v.errors", [{message:"Expense name can't be blank."}]);
        }
        else {
            nameField.set("v.errors", null);
        }
    
        // Amount must be set, must be a positive number
        var amtField = component.find("amount");
        var amt = amtField.get("v.value");
        if ($A.util.isEmpty(amt) || isNaN(amt) || (amt <= 0.0)){
            validExpense = false;
            amtField.set("v.errors", [{message:"Enter an expense amount."}]);
        }
        else {
            // If the amount looks good, unset any errors...
            amtField.set("v.errors", null);
        }
        */
        return(validItem);
	},
    
    createItem: function(component, newItem) {
        var action = component.get("c.saveItem");
        alert(JSON.stringify(newItem));
        action.setParams({"newItem": newItem});
        action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "ERROR") {
                var errors = response.getError();
                if (errors && errors[0]) {
                    console.log(errors[0]);
                }
                else {
                    console.log("Unknown error");
                }
            }            
            else if (component.isValid() && state === "SUCCESS") {
                var items = component.get("v.items");
                items.push(response.getReturnValue());
                component.set("v.items", items);
            }
        });
        $A.enqueueAction(action);
    }
})
Thanks  !





 
Best Answer chosen by Stéphane Bernhardt SalesForce
Gordon EngelGordon Engel
The stack trace (you can't access the exception log output, but I can) says that you're putting an Expense__c into your Camping_Item__c attribute, so the error is probably here:
 
<aura:attribute name="newItem" type="Camping_Item__c"

     default="{ 'sobjectType': 'Expense__c',
                    'Name': '',
                    'Price__c': 0,
                    'Quantity__c': '',
                    'Packed__c': false }"/>

 

All Answers

Gordon EngelGordon Engel
The stack trace (you can't access the exception log output, but I can) says that you're putting an Expense__c into your Camping_Item__c attribute, so the error is probably here:
 
<aura:attribute name="newItem" type="Camping_Item__c"

     default="{ 'sobjectType': 'Expense__c',
                    'Name': '',
                    'Price__c': 0,
                    'Quantity__c': '',
                    'Packed__c': false }"/>

 
This was selected as the best answer
Stéphane Bernhardt SalesForceStéphane Bernhardt SalesForce
Hi,

You're right. Thanks for you answer, I will be able to continue my trailhead module :)
David Roberts 4David Roberts 4
What a strange challenge! I followed the expenses structure and achieved a working camping app - but it failed the challenge.
After many attempts at restructuring, I finally solved it. Here's my code:
 

camping.cmp

<aura:component   controller="CampingListController">
<!-- the Apex server side controller -->
<aura:attribute name="items" type="Camping_Item__c[]"/>
<c:campingHeader />
                <c:campingList items="{!v.items}"/>       
</aura:component>
 

campingList.cmp

<aura:component  controller="CampingListController">
    <aura:attribute name="items" type="Camping_Item__c[]"/>
<aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
  
        <aura:attribute name="newItem" type="Camping_Item__c"
                    default="{'sobjectType' : 'Camping_Item__c',
                               'Name':'',
                               'Quantity__c' : '',
                               'Price__c' : ''}"/>
   
       
  <!-- BOXED AREA -->
  <fieldset class="slds-box slds-theme--default slds-container--small">
 
    <legend id="newCampItemForm" class="slds-text-heading--small
      slds-p-vertical--medium">
      Add Camping Item
    </legend>
 
    <!-- CREATE NEW CAMPING ITEM FORM -->
    <form class="slds-form--stacked">
 
      <div class="slds-form-element slds-is-required">
          <div class="slds-form-element__control">
              <ui:inputText aura:id="campItemName" label="Camping Item Name"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Name}"
                  required="true"/>
          </div>
     </div>
 
     <div class="slds-form-element slds-is-required">
          <div class="slds-form-element__control">
              <ui:inputNumber aura:id="quantity" label="Quantity"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Quantity__c}"
                  required="true"/>
 
          </div>
      </div>
 
      <div class="slds-form-element">
          <div class="slds-form-element__control">
              <ui:inputCurrency aura:id="price" label="Price"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Price__c}"/>
          </div>
      </div>
 
      <div class="slds-form-element">
          <ui:inputCheckbox aura:id="packed" label="Packed?"
              class="slds-checkbox"
              labelClass="slds-form-element__label"
              value="{!v.newItem.Packed__c}"/>
      </div>
 
      <div class="slds-form-element">
          <ui:button label="Create Camping Item"
              class="slds-button slds-button--brand"
              press="{!c.clickCreateItem}"/>
      </div>
 
    </form>
    <!-- / CREATE NEW CAMPING ITEM FORM -->
 
  </fieldset>
    <!-- / BOXED AREA -->
   
   
   
 
   <div class ="slds-card slds-p-top--medium">
        <header class ="slds-card__header">
            <h3 class = "slds-text-heading--small">Items</h3>
        </header>
 
        <section class ="slds-card__body">
               <div id="list" class = "row">
               <aura:iteration items="{!v.items}" var="item">
                    <c:campingListItem item="{!item}"/>
                </aura:iteration>
            </div>
        </section>
 
    </div>
 
</aura:component>
 

campingListController.js

({
              
    // Load camping items from Salesforce
    doInit: function(component, event, helper) {
   
        console.log("call c.getItems: ");
        // Create the action
        var action = component.get("c.getItems");
        console.log("back from c.getItems: ");
   
        // Add callback behavior for when response is received
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                component.set("v.items", response.getReturnValue());
            }
            else {
                console.log("Failed with state: " + state);
            }
        });
   
        // Send action off to be executed
        $A.enqueueAction(action);
    }, //doInit
   
   
    clickCreateItem: function(component, event, helper) {
       
        if(helper.validateCampingItem(component)){
            // Create the new camping item
            var newCampingItem = component.get("v.newItem");
            console.log(newCampingItem);
            helper.createItem(component, newCampingItem);
        }
 
 
    }, //clickCreateItem
   
})
 

campingListHelper.js

({
              
   createItem: function(component, campItem) {
       
        var action = component.get("c.saveItem");
        console.log('create');
        console.log('campitem='+campItem);
        action.setParams({ "campItem": campItem });
        console.log('back from set params');
        action.setCallback(this, function(response){
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                var items = component.get("v.items");
                items.push(response.getReturnValue());
                component.set("v.items", items);
            }
        });
        $A.enqueueAction(action);
       
    },//createItem
   
 
    validateCampingItem: function(component, item) {
       
         // Simplistic error checking
        var validItem = true;
        console.log("validate item");
 
 
          // Name must not be blank
        var nameField = component.find("campItemName");
        var itemname = nameField.get("v.value");
        console.log("itemname="+itemname);
        if ($A.util.isEmpty(itemname)){
            validItem = false;
            nameField.set("v.errors", [{message:"Item name can't be blank."}]);
        }
        else {
            console.log("good name "+itemname);
            nameField.set("v.errors", null);
        }
 
 
                              // Price must not be blank
        var priceField = component.find("price");
        var itemprice = priceField.get("v.value");
        console.log("itemprice="+itemprice);
       
        if (isNaN(itemprice)){
            validItem = false;
            priceField.set("v.errors", [{message:"Item price can't be null."}]);
        }
        else {
            priceField.set("v.errors", null);
        }
        if ($A.util.isEmpty(itemprice)){
            validItem = false;
            priceField.set("v.errors", [{message:"Item price can't be null."}]);
        }
        else {
            priceField.set("v.errors", null);
        }
       
        if (itemprice<0.01){
            validItem = false;
            priceField.set("v.errors", [{message:"Item price can't be zero."}]);
        }
        else {
            priceField.set("v.errors", null);
        }
 
 
        // Quantity must not be blank
        var qtyField = component.find("quantity");
        var itemqty = qtyField.get("v.value");
        console.log("itemqty ="+itemqty);
       
        console.log("now check empty"+qtyField);
        if (isNaN(itemqty)){
            console.log("bad qty ="+itemqty);
            validItem = false;
            qtyField.set("v.errors", [{message:"Item quantity can't be null."}]);
        }
        else {
            console.log("good");
            qtyField.set("v.errors", null);
        }
        if ($A.util.isEmpty(itemqty)){
            console.log("bad qty ="+itemqty);
            validItem = false;
            qtyField.set("v.errors", [{message:"Item quantity can't be null."}]);
        }
        else {
            console.log("good");
            qtyField.set("v.errors", null);
        }
        if (itemqty<1){
            console.log("bad qty <1 ="+itemqty);
            validItem = false;
            qtyField.set("v.errors", [{message:"Enter an Item quantity."}]);
        }
        else {
            console.log("good");
            qtyField.set("v.errors", null);
        }
       
     
        return(validItem);
       
    } //validateCampingItem
})
 

campingListItem.cmp

<aura:component >
    <aura:attribute name="item" type="Camping_Item__c"/>
   
    <p>Name:
        <ui:outputText value="{!v.item.Name}"/>
    </p>
    <p>Quantity:
        <ui:outputNumber value="{!v.item.Quantity__c}"/>
    </p>
    <p>Price:
        <ui:outputCurrency value="{!v.item.Price__c}"/>
    </p>
    <p>Packed?:
        <ui:outputCheckbox value="{!v.item.Packed__c}"/>
    </p>
</aura:component>
 

CampingListController.apxc

public with sharing class CampingListController {
 
    @AuraEnabled
    public static List<Camping_Item__c> getItems() {
       
        // Check to make sure all fields are accessible to this user
        String[] fieldsToCheck = new String[] {
            'Id', 'Name', 'Quantity__c', 'Price__c', 'Packed__c' };
 
system.debug('fields: '+fieldsToCheck);
       
        Map<String,Schema.SObjectField> fieldDescribeTokens =
            Schema.SObjectType.Camping_Item__c.fields.getMap();
   system.debug('map: '+fieldDescribeTokens);    
        for(String field : fieldsToCheck) {
            if( ! fieldDescribeTokens.get(field).getDescribe().isAccessible()) {
                throw new System.NoAccessException();
                return null;
            }
        }
       
Hope this helps.
Nathan HincheyNathan Hinchey
I'm having the exact same issue. Why is there no way to view exception logs?

In hopes that a Salesforce employee will take pity on me and let me know the output from mine, here's the error I got:
 
An internal server error has occurred
Error ID: 39586319-139057 (119852647)

For future reference, though, how would I go about debugging this? The error output is extremely unhelpful.
Gordon EngelGordon Engel
Please provide the rough day and time when the error occurred and the instance you saw it on.  The error you hit seems to be an invalid type mismatch, which shows up in numerous ways.  I could run a search across the universe of logs on your unique Error ID, but it will be a lot more efficient if you help me with the instance and date/time.

To answer, "Why is there no way to view exception logs?":

Exceptions have always been suppressed so I can't say for sure what the founders of Salesforce were thinking, but my hunch is that exceptions (backtraces) provide details about your app architecture that is useful to developers but confusing to users.  They could also provide an attack vector for malicious people looking for a weakness.
Gordon EngelGordon Engel
I found the exception:

apex://CampingListController/ACTION$saveItem error: apex://CampingListController:11,1: common.apex.runtime.impl.ExecutionException: Attempted to upsert a null list

Hope this helps.