Ever been on a Dynamics CRM/365 record’s form, life is good, you’ve got your morning coffee in one hand, the birds are singing and you’re clicking around, happy as can be?
Suddenly, you save some changes. Boom. Morning ruined. “Where’s the ribbon gone?” you exclaim. You refresh the form, and on exit you get the standard “Send a report to MS” error dialog. Being the good CRM developer that you are, you don’t just want to pass the buck to our friends in Redmond. You hit the “View the data that will be sent to Microsoft” link.  Maybe the exception is something telling.

<ScriptErrorDetails>

<Message>Unable to get property ‘toString’ of undefined or null reference</Message>

<Line>1</Line>

<URL></URL>

<PageURL>/form/page.aspx?alotofparameters=1</PageURL>

<Function>anonymousr:Unabletogetproperty’toString’ofundefinedornullreference</Function>

<FunctionRaw>TypeError: Unable to get property ‘toString’ of undefined or null reference</FunctionRaw>

<CallStack>

<Function>anonymousr:Unabletogetproperty’toString’ofundefinedornullreference</Function>

</CallStack>

</ScriptErrorDetails>

 

Hey hey hey, look, I said maybe! Put the tar and feathers down…please? So, all this tells us is that somewhere out there, an anonymous JavaScript function has tried to call toString() on an object that doesn’t exist. Well this should be easy to find the source of…hand me that rope, please.

Cutting a long story short, I found the error by using Google Chrome’s DOM breakpoints to identify what code was manipulating the ribbon. From there it was a matter of painfully stepping through the minified CRM JavaScript. I finally managed to grab the internal object that had the method that was reloading the ribbon. I called it, and sure enough, there was an error that looked a lot like the one in the error dialog.

Uncaught TypeError: Cannot read property ‘toString’ of undefined
at Function.Mscrm.CommandBarBuilder.$HE (ribbon.js?ver=-1857050180:formatted:1381)
at Mscrm.ButtonControl.get_element (ribbon.js?ver=-1857050180:formatted:1934)
at Mscrm.CommandBar.get_commandBarContent (ribbon.js?ver=-1857050180:formatted:951)
at Mscrm.CommandBar.refreshCommandBarContent (ribbon.js?ver=-1857050180:formatted:1029)
at Mscrm.CommandBar.resizeCommandBar (ribbon.js?ver=-1857050180:formatted:1102)
at Mscrm.CommandBarBuilder.resizeCommandBar (ribbon.js?ver=-1857050180:formatted:1462)
at Mscrm.RibbonManager.$EA_3 (ribbon.js?ver=-1857050180:formatted:4859)
at Mscrm.RibbonManager.$B7_3 (ribbon.js?ver=-1857050180:formatted:4178)
at Mscrm.RibbonManager.$Dc_3 (ribbon.js?ver=-1857050180:formatted:4561)
at Mscrm.CommandBarData.reloadCommandBar (JsProvider.ashx?bundle=CommonExtendedBundle&ids=1…)

So, digging in, I found this function (Still minified, but pretty printed to prevent eye bleeding).

Mscrm.CommandBarBuilder.$HE = function ($p0) {

var $v_0 = {}, $$dict_3 = $p0;

for (var $$key_4 in $$dict_3) {

var $v_1 = { key: $$key_4, value: $$dict_3[$$key_4] };

$v_0[$v_1.key] = CrmEncodeDecode.CrmHtmlAttributeEncode($v_1.value.toString());

}

return $v_0;

};

Behold our toString method. And sure enough, it forgets to check if  $v_1.value is null before accessing it. So where is this null value coming from? Well, if we look at the parameter being passed along when the error occurs…

$p0 =

{

Alt: “So…”,

Command: “incident|No…”,

Description: “I’m a button!…”,

Id: “incident|No…”,

Image16by16: “/%7B6362136…”,

Image32by32: “/%7B6362136…”,

LabelText: “Submit”,

ModernImage: “$webresourc…”,

Sequence: “53”,

TemplateAlias: “o1”,

ToolTipDescription: “Someting something…”,

ToolTipTitle: undefined

}

…you may notice that the object’s properties match a ribbon button’s perfectly. And sure enough, it is throwing the exception when it reaches one of our custom ribbon buttons. So I fire up Ribbon Workbench, and confirm that our tooltip has no title, just like in the object above.

 

So what is happening here? Well, judging from the none-minified method names in the method that’s throwing the exception, I’m betting that it’s job is to format/sanitise the strings from the ribbon button properties before they are added as attributes to the ribbon’s HTML elements. Unfortunately, the author overlooked that someone may leave a button property blank, and that’s when the error happens. So why doesn’t this happen right when you load the form? Near as I can tell, the initial render of the ribbon uses different code and the bug is only triggered when the ribbon is reloaded.

I’ve had colleagues mention seeing this error on both CRM 2016 and Dynamics 365. In all the cases I’ve heard of it’s been on Online instances.

Naturally, I don’t expect that everyone who gets this TypeError on CRM is having this problem, as it is far too generic an error for that to be the case. I also don’t expect this is the only bug that makes your ribbon disappear. If you do have any examples of other cases of either, feel free to leave a comment below.

TL;DR

Ok. Fine. Your custom ribbon button is missing some properties. Fix it by filling these out and all will be peachy. If any of the following button properties are blank the error will occur.

  • Alt
  • Command
  • Description
  • Id
  • Image16by16
  • Image32by32
  • LabelText
  • ModernImage
  • Sequence
  • TemplateAlias
  • ToolTipDescription
  • ToolTipTitle

Comments

comments