10

I must be missing something here..I have a visualforce page, that enables a user to create a Campaign - I have a pageblock/section with the Campaign Fields, including name, and Name is marked required. I click a button, and if the name field for Campaign is blank, I get this error:

System.FinalException: SObject row does not allow errors

In the logs, the line before my error is a VF Page Message "You Must Enter a Value", but instead of throwing the error back to the user, the next line is:

EXCEPTION_THROWN [EXTERNAL]|System.FinalException: SObject row does not allow errors

And the thing is, if I remove all code in the pagereference call in the controller, and just return null, it still gives the error, but as far as I can tell, I am not writing anything to the database?

Update - apparently, it is this line causing my issue:

newCampaign = (Campaign)Campaign.sObjectType.newSObject(null, true);

if I use the standard way:

newCampaign = new Campaign();

the page works just fine.

Is that expected behavior?

8
  • Is it worth setting immediate=true on the button click if its only doing a partial page refresh? Commented Dec 20, 2012 at 20:51
  • No - I want the page level validation to fire - if there is no Campaign Name, I want to stop the submit - but for some reason, it doesn't stop - it takes me to this error instead? Commented Dec 20, 2012 at 22:39
  • I don't see anything in the sObjectType.newSObject documentation that would lead me to believe it should behave differently. Do you get the error when you explicitly set the default values in the new Campaign() constructor? In other words, make it so that newCampaign has all of the same field values as it would have had from the newSObject call (might need to set RecordTypeId, too). Commented Dec 21, 2012 at 3:21
  • Thanks = it's been driving me mad all day trying to work this out...I'm in dev environment with no Campaign Record Types...so that shouldn't be an issue. I see what you are saying - but if I use the sObject method, and set a name it works just fine - so doesn't seem to be a default value issue - it just doesn't seem to apply the correct validations for a Campaign object before it tries to save, and then falls over because there isn't a name (which is required at the db level) Commented Dec 21, 2012 at 3:48
  • Seems like a bug to me, have you filed a case with support? Commented Jan 31, 2013 at 4:45

4 Answers 4

4

As mentioned in my comment, it's a bug. I got a response from Salesforce today confirming it.

Here is the bug in the known issues tracker:
https://success.salesforce.com/issues_view?id=a1p30000000Sz5RAAS

As you have deduced it is caused when an object is instantiated using the SObjectType.newSObject method, but only when the useDefaults flag is true. Which without it defeats the purpose of instantiating the Campaign record in that way.

1

From reading the details of the feature, and your statement about not performing DML, I'd say this is a possibly a bug. The newSobject method should just instantiate a new Campaign with the default values and default record type given the way you called the method.

Can you post more of the method you're calling when they create the campaign? You're not trying to use addError directly on the instantiated SObject if they forgot Name are you?

0

I had the same issue and putting a <apex:pageMessages /> on my VF page helped me figure out the root cause of this error.

0

I have found a successful work around for this issue that still allows users have the defaulted values while not getting an error for their troubles.

Essentially you create an object that has been set with defaults and one that has not. Then using field describes, go field by field, and copy the values from the defaulted sobject the other that has not been.

Here is the function that I use to get around this particular hurtle:

    /**
     * This method will create get the default values for an sobject record bypassing a known issue
     * that can cause an error, "SObject row does not allow errors" on a visualforce page
     * @return The sobject record with the correctly defined default values
     */
    public static SObject getSobjectDefault(String sobjectName) {
        Schema.SObjectType targetSobjType = Schema.getGlobalDescribe().get(sobjectName);
        //Need to have two sobjects, one initialized with default values one without
        SObject sobjDefaultRecord = targetSobjType.newSObject(null, true);
        SObject actualSobjRecord = targetSobjType.newSObject();

        //Need to use the describes to copy the default data into the actual sobject record that Visualforce
        //will use
        Schema.DescribeSObjectResult sobjDescribe = sobjDefaultRecord.getSObjectType().getDescribe();
        Map<String,Schema.SObjectField> fldMap = sobjDescribe.fields.getMap();

        //Going through each field so we can move the data from the default record into actual sobject record
        for (String fld : fldMap.keySet()) {

            //Using object so we do not need to cast the correct type
            Object defVal = sobjDefaultRecord.get(fld);
            Schema.DescribeFieldResult dfr = fldMap.get(fld).getDescribe();

            //Because we are going through every field, need to ensure that we copy fields that are able to be copied. 
            //Specifically ran into a problem with the isDeleted field in particular, which is not writable
            if (defVal != null && dfr.isPermissionable() && dfr.isCreateable()) {
                actualSobjRecord.put(fld, defVal);
            }
        }
        return actualSobjRecord;
    }

You must log in to answer this question.

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