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
LeadClic DeveloperLeadClic Developer 

Summer '13 now working always with 18 char IDs. This can cause code issues.

It seems that the new Summer'13 update enforces you to work with 18 character ID's always. For example, this happens in apex:

 

Id Id15 = string.valueOf(Id18).substring(0,15);
System.AssertEquals (Id15,Id18);

 

Pre-Summer that assertion fails, as Id15 is the 15 character Id and Id18 is the 18 character Id.
In our custom code many times we use Custom Setting and Custom Labels to avoid hardcoding recordtypes, profiles and other "constant" values. We usually worked with 15 character Ids as Salesforce (SOQL) sometimes returns 15 and other times returns 18 character Ids.

 

Now it seems the ID type always returns 18 character, if you do something like this the assertion is true:

 

Id Id15 = '012200000005byN';
System.AssertEquals (Id15,'012200000005byNAAQ');

 

As this is happening now with the Summer'13 but not happening before with Spring'13, this invalidates many coding.

We found this problem as Salesforce triggered a deep system error like this Salesforce System Error: 1619326252-34083 (1564369920) (1564369920) trying to compare a SelectOption loaded with record types with a Custom Settings String Id Stored.

 

This is a really weird annoyance. You can take a workaround working always with ID type instead of storing Ids into Strings, and always working with 18 character Ids, wether you hardcode Ids into apex and formulas (not a good approach) or you use custom setting and labels to store the ids.

 

Hope this helps... I lost all morning trying to figure out this.

docbilldocbill

Close, but no cigar.   We have code like the following:

 

            for(Task tk : newMap.values()) {
                if(tk.RecordTypeId == Util.tandemRecordTypeId) {
                    ...

                }
            }

The comparison generates the an exception with Summer '13.  However, when I look in the Util class I see tandemRecordTypeId defined as:

 

    public static final Id tandemRecordTypeId='01260000000574LAAQ';

So there is no 15 character Id's in use, and everything is an Id type field...   Something much more fundamental must be happening.

 

 

LeadClic DeveloperLeadClic Developer

In my case, the exception popped out in a comparison too, in my case the comparison was between a property that contains the value of a VF Selected Option an the RecordTypeId inside a Custom Setting:

 

public Id SearchType{get; set;}

...

if (SearchType ==ProductSettings.RecordTypeId_Pack__c) ...

 

I converted SearchType from Id to string instead, that solved the exception problem.

 

Probably, if you define Util.tandemRecordTypeId as String instead of Id you can Workaround the Issue, try and tell me if it worked.

 

I think there is some really weird type conversion inside SF Engine that at some point determines that an Id is not a String or the opposite. Now as Id type always converts to 18 even if you feed it with 15, there must be some new internal conversion funcions inside.

docbilldocbill
Yeah. The string conversion works. Only to do it properly one has to make sure they are comparing 18 character Id's as string. This is probably a good workaround if one absolutely needs a single class or method to work TODAY. But for our own organization the amount of code impacted is too huge to even consider updating everything. We have about 60% automation on our testing. So we probably be looking at a month of QA time to test the other 40% manually.
LeadClic DeveloperLeadClic Developer

I'm with you... this sudden change (and exception) in how Id's are handled are a BIG problem right now. Probably in most cases changing from Id type to String type will do the trick... but many people has 15 digit Id's hardcoded or filled in labels and custom settings that will not work.


There is a lot of work behind to ensure apex will be working properly in Summer'13.

 

It's hard to chew that SF didn't take this issue into account. I opened a case for this and I've received no help... as it was urgent I tweaked my code till I found the workaround.

davidjgriffdavidjgriff

I have a similar issue that seems to have cropped up. A simple describe call on an Id is now failing with one of those lovely low level system errors that doesn't do much to help me fix it :)

 

This line

 

Schema.DescribeSObjectResult d = objId.getSObjectType().getDescribe();

 throws

FATAL_ERROR System.UnexpectedException: Salesforce System Error: 1667812007-36686

 

objId is just an ID passed into a VF component from a VF page using a standard controller, so I know the ID is valid. I can see the ID in the log output and if I run the same code in an execute anonymous block, all is well. It only seems to break when being used in the component controller.

docbilldocbill

That sounds like a very important clue.  If the describe fails, then I bet the code which automatically casts strings to Id fields is failing at the point of determining if the value is a String.

 

davidjgriffdavidjgriff

The funny part is, I can see the ID that was cast from the string within all the debug logs. It made its way to an ID, but something screwy is happening after that. Support is "looking into it" and will get back to me....

docbilldocbill

Not quite so funny.

 

Here are the possible ways one can test two id values:

 

  1. if( idValue == idValue2)
  2. if( idValue == stringValue)
  3. if( stringValue == idValue)
  4. if( idValue.compareTo(stringValue) == 0)
  5. if( stringValue.compareTo(idValue) == 0)


I know in my code I always do #1.  That is failing.   Based on the information in this thread I would predict #3 and #5 would also fail.  #2 and #4 might work.  I would have to test them to know.

 

 

kaplanjoshkaplanjosh

LeadClic Developer, I just attempted to reproduce the behavior here, and I cannot get either of these items to fail.

 

Your assertion is not failing pre-summer.  It is possible to make that code fail, but unless you provide the code which creates the Id18 variable, there's no way to guarantee that I'm mimicking your behavior.  Your second bit of code is also behaving the same way as it did in previous versions.  If you insert system.debug(Id15); you will see that the ID is output as an 18-digit ID

 

Id Id15 = '012200000005byN';
System.debug(Id15); System.AssertEquals (Id15,'012200000005byNAAQ');
kaplanjoshkaplanjosh

docbill:  There is a bug with how static final variables are handled.  This will be fixed in a patch prior to the main release window.  I believe this will solve your issue.

docbilldocbill

Don't worry about it.  Our organization has many failing examples for salesforce to look at.  As it sounds like so do others.  Interesting enough, I see some code that is almost identical to the failing code that works.  So there is probably some subtly that is not readily obvious on visual examination.   Which is another reason why we are very lurry to attempt any sort of work-around.  It could be a workaround would resolve the problem for our test cases, but not the end users.

 

docbilldocbill

Josh, that sounds great.  I'll start looking to see if all of the failure cases all involve static variables.   Our organization has  three different development teams all who will be twittling their thumbs until this is fixed, once we run out of investigate type tasks.  The problem is so wide spread pretty much all development and testing is blocked.   So it is costing our organization about  20 - 30 thousand dollars per day in salaries, waiting for this to be fixed. 

 

Obviously that the sooner a fix can be deployed, the better.

 

kaplanjoshkaplanjosh

Could you post some examples for me to look at?

docbilldocbill

Josh, I searched our organization and I only found confirmed failures where one argument was a static Id.   Purhaps someone else in this thread has a specify example of a different failure type.

 

 

kaplanjoshkaplanjosh

FWIW, we were using 18-character IDs in the last release as well.  Try this code in your production or DE org, which should still be using Spring '13:

 

Account a = [select id from Account limit 1]; 
String sID = String.valueOf(a.id).substring(0,15);
ID myID = sID;
system.debug(myID);

You will see that even in Spring release the ID field was 18-characters.  This is not the root issue here.

 

Please send along more detail on the code that is giving errors, so I can help with the issues you are seeing.

LeadClic DeveloperLeadClic Developer

This example Crash Dives, I've tested it and causes the exception.

 

First you'll need a new Custom Settings called "Products__c", type of the Custom setting is LIST and it'll need only one instance called "General" and one field (string 15) called RecordTypeIdPack__c with one of your Quote Id's

Probably you could mimic this without creating the custom setting, but I included it for the example to be as accurate as possible.

 

Next you'll need this page:

<apex:page standardController="Quote" extensions="ProductWizardERRORTEST" sidebar="false" tabStyle="Quote">
	<apex:form >
		<apex:pageblock id="SearchBlock" title="Search Block" mode="detail" rendered="{!ShowSearchForm}">
			<apex:selectList id="selectTipo" value="{!SearchType}" size="1">
				<apex:selectOptions value="{!lSelectType}"/>
	        		<apex:actionSupport event="onchange" action="{!EvaluateVisibility}" rerender="SearchBlock"/>
			</apex:selectList>
		</apex:pageblock>
	</apex:form>
</apex:page>

 And the Class behind:

public class ProductWizardERRORTEST {
	// Properties for the select list
	public boolean ShowSearchForm {get;set;}
	public Id SearchType {get; set;}
	public list <SelectOption> lSelectType {
		get{
			if (lSelectType == null){
				list <SelectOption> lSelectTypeAux = new list<SelectOption>();
				List<RecordType> lRT = [SELECT Id,Name FROM RecordType WHERE SobjectType='Product2'];
				for (RecordType rt :lRT) lSelectTypeAux.add(new SelectOption(rt.Id,rt.Name));
				return lSelectTypeAux;
			} else return lSelectType;
		} set;
	}
	// Product record types custom settings Initialization
	Products__c ProductConfig {
		get{
			if (ProductConfig == null)
				return Products__c.getInstance('General');
			else 
				return ProductConfig;
		}
	}
	
	// Constructor
	public ProductWizardERRORTEST(ApexPages.StandardController controller) {
		ShowSearchForm = true;
	}

	// Method that crashes
	public void EvaluateVisibility(){
		// THE ERROR TRIGGERS IN THE NEXT LINE
		if (SearchType == ProductConfig.RecordTypeIdPack__c){
			ShowSearchForm = false;
		}
	}
}

 

Now open the page and change the value of the picklist and... BAM!

 

Salesforce System Error: 1935329124-80909 (1564369920) (1564369920)

El error está en la expresión '{!EvaluateVisibility}' en page productwizarderrortest


Se ha producido un error inesperado. Se ha notificado a su organización de desarrollo.

 

I hope that helps.

 

*** EDIT ***

 

I forgot to say  that if you change the ID property to String, then it doesn't fail:

 

public String SearchType {get; set;}

 

 

cmendlercmendler

We got pointed to this known issue: https://success.salesforce.com/issues_view?id=a1p30000000SwKWAA0

 

Unfortunately it is currently scheduled or May 23rd release and we are crippled without a fix.   Definitely need this released TODAY if it is indeed the proper fix

davidjgriffdavidjgriff
Interestingly enough, one of the workarounds noted in that issue brings to light another bug that I just stumbled upon in another piece of code.

I can't compile a class that uses the "Id.valueOf()" method. It throws a "Variable does not exist, Id" error.

I can execute anon the same code and it runs just fine, but it won't save/compile through the IDE.
kaplanjoshkaplanjosh

LeadClic, this is the same issue as i mentioned earlier.  It has been fixed and will be released as soon as it is prudent to do so.

 

Please understand that we need to be deliberate when fixing things that are being rolled out to over 100,000 customers.  We want to make sure we don't inadvertently break something equally important while fixing this.  We are working on it - thank you to everyone for providing details here, and thank you for your patience as we get this right.

docbilldocbill
For us, the Id.valueOf is working well. e.g.

public static final Id tandemRecordTypeId=Id.valueOf('01260000000574LAAQ'); // tmp change

It is a little ugly, but it works.

We only found two locations in our code dealing with Id's where the error was not caused by "static final Id". Both of those are still a mystery to us, as to why they fail when other similar type code works. However, we did manage to code workarounds. One of the mystery ones is we had a field:

Id recordId {
get;
set;
}

in one of our controllers. When the recordId was compared to, there was always a system error. The workaround was:

Id recordId {
get { return (recordId != null)?Id.valueOf((String)recordId):null; }
set;
}

This works. But why it works is a mystery. We only found it by just trying semi-random changes... My guess is there is a problem type stored when the Id value is set from within the component, but that is just a guess.

The other case was even more strange. I'm not entirely convinced the other case is a Spring'13 problem, so I won't quote it here.

Bill
kevoharakevohara

Allow me to chime in here with another possible issue. :)

 

We started to see failures in our managed package when Summer '13 started hitting sandboxes. We traced the issue down to a spot where we were type checking Objects and looking for instances of Id's. This isn't the actual code, but my best hand-typed example of how it worked.

 


private Boolean testField(Object obj) {
if(obj instanceof Id) { return true; }
return false;
}

SObject so = [SELECT Id, Text_Field__c FROM MyObject__c WHERE ID = :someId LIMIT 1];

System.debug(so.get('Text_Field__c')); // => "FooBar"

testField(so.get('Text_Field__c')); // => true!!!!

 

In our case, Text_Field__c was an actual String value and not an Id but the instanceof comparison above was evaluating to true and crashing our app. This was only happening within triggers and not able to be reproduced using anonymous apex. We are currently working up an example trigger in hopes we can provide a re-producable test case that we can share.

 

Anyone else seeing this?

CBlandCBland

To follow up on what Kevin said, here are reproducable tests to show this error. 

 

This error occurs when passing an Object that has the type String to a method that runs an InstanceOf against an ID

 

Gist with Tests showing this bug

https://gist.github.com/ChrisBland/5721696

 

public class TriggerHandler{
  public TriggerHandler(){}
  public Boolean isInstanceOf(Object obj){
    if(obj InstanceOf ID){
      return true;
    }else{
      return false;
    }
  }
}

 

@isTest
private class TestIDs {
	
	@isTest static void test_method_one() {
		// Implement test code
    Map<Id,SObject> oldMap = new Map<Id,SObject>();
    
    Opportunity o = new Opportunity();
    o.Name = 'Test Oppty';
    o.StageName = 'Prospecting';
    o.CloseDate = System.Today().addDays(5);
    Database.Insert(o);
    oldMap.put(o.Id, o);
    
    TriggerHandler th = new TriggerHandler();
    SObject sobj = oldMap.values()[0];
    
    Boolean isPicklistId = th.isInstanceOf( sobj.get('StageName') );
    Boolean isDateId = th.isInstanceOf( sobj.get('CloseDate') );
    Boolean isStringId = th.isInstanceOf( sobj.get('Name') );
    
    System.AssertEquals(isPicklistId, false); ==> THIS FAILS
    System.AssertEquals(isDateId, false);
    System.AssertEquals(isStringId, false); ==> THIS FAILS
  }
}

 

 

 

cbrocbro

Are th 18 characters now going to appear in the URL, as well?

 

up until now, it's been only the 15 characters - and it appears it's still only 15 characters.  (at least in the sandbox)

 

Thanks,