Yeah. I forgot I started this series. I’m only human.
I remembered it when I was thinking about this story I’m about to share (names and places changed to protect the innocent), so here it is.
(BTW, I was inspired to write in this style by the creative work of my friends at Nerdforce!)
I’m a professional, see; I don’t configure big changes in Production. I do it in a sandbox, like the big shots.
The changes were easy – one record type that needed some minor adjusting. A field added here, another field removed, a picklist value added there. Some workflows. It was the kind of work that I had done hundreds of times before. I know how to write a formula, know about adding the picklist value to the record type.
The only hiccup? A validation rule that needed to fire for other record types but would’ve spelled bad news for users of this one.
But I’m not just any dame. I’m an Admin. I didn’t break the rule, but I bent it, making sure that my record type could slip in under the radar. I knew I wanted to be precise, so I added NOT(RecordTypeID = [long string of random numbers and letters]). It’s nothing I haven’t done before. It takes a lot more than record types to get under my skin nowadays.
And my client? Another satisfied customer.
After only two hours of work, I created my change set, pushed to production, and disappeared into the night.
Then things got quiet.
Until my phone rang.
“Admin! Thank Benioff! We’ve got a real problem brewing down here.”
“Oh, yeah, what’s that?”
“Well that record type, ya see, it’s workin’ great except that no one can save a record. There’s a problem. It’s flashing red, and it don’t look good, kid.”
Undeterred, I flipped open my trusty laptop, “Tell me what it’s saying.”
“It’s an error message. It wants us to give it a value in some field, but we ain’t got the picklist. It’s sayin’ it won’t give up the record without it. What are we gonna do?”
I had to think fast. I had tested that very validation rule. Playing it cool, I asked, “Are you getting this error every time?”
“No. We didn’t even know it knew about this record type. Should we just…give it what it wants?”
“Don’t do that. But give me a minute to think,” I assured the client.
Like the flash of a muzzle, the answer came to me. Yeah, I had done this before, but here I was, caught like a fly in the syrup. Like some two-bit beat admin with something to prove and nothing to back it up with.
The change set. I should have caught it sooner, should have known. It had been staring me in the face. But I had to make sure.
“Let me call you back,” I said.
I hung up and stared at the screen for a minute. So this was how I would be done in.
I opened the validation rule. There it was – that 18 digit code. 18 characters between me and solving this case. I knew the answer; I wasn’t stupid, but I had to look anyway. I opened the record type. Different ID. The switch had been made right under my nose.
I’m no fool, and no change set was gonna best me.
I copied that ID, replaced it in the validation rule and saved. Not about to look bad in front of my client, I tested the change. Purred like a kitty cat.
The ringing on the other end was shrill, like it was shouting the client’s concerns.
“Yeah, it’s me,” I smirked, “and I solved the problem. You won’t be getting that error message again.”
I waited while they tested it, and I disappeared during the celebration. They would be fine, I knew.
So the moral of the story here should be pretty simple: don’t hardcode IDs in your formulas or validation rules in a sandbox. Because they will be different in production.
Understanding multi-tenant architecture (which I swear, I do!), it makes sense. You can’t have the same unique identifier in two separate orgs. That would create chaos. And a sandbox doesn’t get any special treatment.
So really, you have a few options here:
- Temporarily turn off the validation rule in sandbox and remember to update it in production.
- Make the change in sandbox and duplicate in production.
- Don’t use the ID – use the name. You can always change it later if need-be.
- Don’t ever use Record Types
- Don’t ever use Validation Ruls
Disclaimer: Numbers 4 and 5 are not actually options.
Either way, something like this isn’t the end of the world. But it is definitely good to keep in mind, especially if pushing changes to production late at night or early in the morning when users are less likely to be active, but you’re caffeinated and raring to go.
Also…full disclosure: this has happened to me more than once. I hope that by sharing my story, I will actually keep myself from repeating my mistake.
Have you learned this same lesson? A similar one that involved using hard-coded IDs?
2 thoughts on “Lessons Learned: Record Type IDs”
You’re right about not using hard-coded Id values, but there is a half-truth in this article I’d like to clear up. When you refresh a sandbox, all record types will have the same Id as they do in production. When you create a new record type and move it via change set, then it will have a different Id than production. In that sense, Id values are not globally unique in the sandbox domain. The same is also true for other types of records, like profiles, roles, users, and other setup data that’s copied during a refresh. This is why people sometimes assume that it is safe to hard-code Id values, until that one time when it causes catastrophic failure with production data.
Fair enough, though in the story, of course, we are creating the RT in a sandbox because we don’t configure in prod. 🙂