11

I have an 18 character SFDC ID. I was under the impression that I should be able to create a link to that record using the following pattern: https://<org server>.salesforce.com/<id>

For example: https://na12.salesforce.com/00TU000000Nf5NP

That link works fine for me. However, when I try to link to the same object using the 18 character, case insensitive ID (ex. https://na12.salesforce.com/00tu000000nf5npmaz), I get the following error:

Insufficient Privileges

You do not have the level of access necessary to perform the operation you requested. Please contact the owner of the record or your administrator if access is necessary.

What exactly is the problem? If all I have is the 18 character ID, how can I create a link back to the correct SalesForce record?

  • do you use the datatype Id, instead of String? – pjcarly Mar 13 '13 at 21:14
  • I don't understand your question. These links are created outside of SalesForce. For example, I may want to just copy and paste them in to the browser directly, so getting the values as an Id or a string should be irrelevant, unless I'm missing something? – Ryan Elkins Mar 13 '13 at 21:16
  • aha, didn't know the id's were generated outside of salesforce, than my question is irrelevant. – pjcarly Mar 13 '13 at 21:19
16

I'm not sure that the case insensitive Ids work like that. With your all lowercase ID I'm guessing Salesforce is looking for an OpportunityShare (keyPrefix 00t) rather than a Task (00T). Odd that they aren't using the suffix information.

The suffix is enough to make the ID appear to be insensitive in something like Excel, but it doesn't mean you can convert it all to lowercase in Salesforce.

Try 00TU000000Nf5NPMAZ on the URL.


Writing something to revert the casing just seemed like too much fun to be left undone.

This is in C#, but I've tried to avoid things like LINQ and framework classes (BitArray) to make it more language agnostic. It does bloat it a bit, but hopefully you get the idea. There are several areas that would benefit from some additional error checking.

private static char[] characterMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345".ToCharArray();

private static bool[] BitPatternForChar(char c)
{
    c = Char.ToUpper(c);

    byte characterMapIndex = byte.MinValue;
    for(byte i = 0; i<characterMap.Length; i++)
    {
        if(characterMap[i] == c)
        {
            characterMapIndex = i;
            break;
        }
    }

    // Get the Bit Pattern for the byte
    bool[] result = new bool[5];
    for (int bitNumber = 0; bitNumber < result.Length; bitNumber++)
    {
        result[bitNumber] = (characterMapIndex & (1 << bitNumber)) != 0;
    }
    return result;
}

public static string RepairCasing(string lowercaseInsenstiveId)
{
    if (string.IsNullOrEmpty(lowercaseInsenstiveId))
    {
        throw new ArgumentNullException("lowercaseInsenstiveId");
    }
    else if (lowercaseInsenstiveId.Length != 18)
    {
        throw new ArgumentException("lowercaseInsenstiveId should be 18 characters", "lowercaseInsenstiveId");
    }

    List<bool> toUpperBits = new List<bool>(15);

    bool[] isUpperCaseChar = BitPatternForChar(lowercaseInsenstiveId[15]);
    toUpperBits.AddRange(isUpperCaseChar);

    bool[] isUpperCaseChar2 = BitPatternForChar(lowercaseInsenstiveId[16]);
    toUpperBits.AddRange(isUpperCaseChar2);

    bool[] isUpperCaseChar3 = BitPatternForChar(lowercaseInsenstiveId[17]);
    toUpperBits.AddRange(isUpperCaseChar3);

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 15; i++)
    {
        Char c = lowercaseInsenstiveId[i];

        if (toUpperBits[i])
        {
            c = Char.ToUpper(c);
        }
        else
        {
            c = Char.ToLower(c);
        }
        sb.Append(c);
    }
    sb.Append(lowercaseInsenstiveId.Substring(15, 3).ToUpper());
    return sb.ToString();
}
  • That looks like it works - when I get the data it has been lower cased by other code - is there a way to convert it back to the proper casing? – Ryan Elkins Mar 13 '13 at 21:24
  • @RyanElkins, yes, I think it should be possible to infer which of the characters should be upper case from the suffix as that is essentially the information they encode about each block of 5 characters. It would be an interesting exercise to complete :) – Daniel Ballinger Mar 13 '13 at 21:29
  • 1
    This is great work @DanielBallinger and it only took 4 edits ;) – Daniel Blackhall Mar 14 '13 at 3:49
  • @DanielBlackhall Ha Ha :) I'm getting better, honest. I'm well with my 10 edit quota. – Daniel Ballinger Mar 14 '13 at 7:54
  • 1
    For posterity, a couple ports to Apex can be seen here. – Adrian Larson May 24 '16 at 21:58
4

The "case-insensitive" Id is not case-insensitive in and of itself. It is unique case-insensitive.

Could SFDC convert the id using the reverse of the algorithm derived from the last 3 digits of the 18? Yes. But we don't. Not being the person who designed or built them, but just another developer in the field like you, near as I can tell we just drop those characters, meaning if you have code that manipulates any of the alpha characters and changes their case, you will have broken the Id.

Only toolkit I've found that fixes these is Ezra Kenigsberg's field utilities google spreadsheet. You can copy it to your own google drive to use it.

  • The Excel Connector also has a fixid function that converts 15 character to the 18 character version – BritishBoyinDC Mar 14 '13 at 3:02
  • Different problem, really. There are a lot of tools that convert 15-char Ids to 18-char Ids, including the CASESAFEID function in SFDC functions. The problem here is a broken 18-char Id due to some external software changing case on the 18-char Id. Do you know if the Excel Connector does that? – pchittum Mar 18 '13 at 9:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.