{"id":5862,"date":"2012-11-01T10:45:32","date_gmt":"2012-11-01T17:45:32","guid":{"rendered":"https:\/\/engineering.fb.com\/posts\/385986644857995\/under-the-hood-the-javascript-sdk-error-handling"},"modified":"2018-12-12T16:05:25","modified_gmt":"2018-12-13T00:05:25","slug":"under-the-hood-the-javascript-sdk-error-handling","status":"publish","type":"post","link":"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/","title":{"rendered":"Under the Hood: The JavaScript SDK &#8211; error handling"},"content":{"rendered":"<p>For the next few weeks we will be exploring the internal details of our <a href=\"https:\/\/developers.facebook.com\/docs\/reference\/javascript\/\">JavaScript SDK<\/a> in a series of posts. Our hope is that this will help developers debug any issues with our SDK and give us an opportunity to outline some cool best practices for JavaScript libraries. In this post, we&#8217;re going to drill into how error handling works in our SDK.<\/p>\n<p>When writing library code targeted at running on third party sites, the only truly known thing is the code that you provide &#8211; everything else is an unknown and potentially unsafe factor:<\/p>\n<ul>\n<li>The browser executing the code<\/li>\n<li>The JS environment, possibly with augmented prototypes or shadowed constructors<\/li>\n<li>Invalid arguments passed to your code<\/li>\n<li>Functions\/callbacks invoked by your code having unexpected side effects or errors<\/li>\n<\/ul>\n<p>Because of this, even &#8220;perfect&#8221; code will in many cases end up misbehaving or throwing errors. So, we&#8217;ve instrumented our JavaScript SDK with code for detecting and reporting such errors back to us for further investigation.<\/p>\n<p>To demonstrate how we do this, we&#8217;re going to walk through a simple scenario: We&#8217;ll create a small library and then instrument it just like we&#8217;ve instrumented the JS SDK. To start off, let&#8217;s create an example that illustrates how many libraries set up their public APIs:<\/p>\n<pre>var mylib = (function () {\r\n  var mylib = { \/\/ this will naively create new properties on our mylib object \r\n    provide: function (name, fn) {\r\n      this[name] = fn;\r\n    }\r\n  };\r\n  ..\r\n  \/\/ create mylib.foo \r\n  mylib.provide('foo', function () {\r\n    ..\r\n  });\r\n  \/\/ create mylib.bar \r\n  mylib.provide('bar', function () {\r\n    ..\r\n  });\r\n  return mylib;\r\n})();<\/pre>\n<p>The conventional way to add library-wide error handling to this code is something like the following:<\/p>\n<pre>function guard(fn) {\r\n  return function () {\r\n    try {\r\n      return fn.apply(this, arguments);\r\n    } catch (e) {\r\n      \/\/ log error \r\n      ..\r\n      \/\/ re-throw to halt execution \r\n      throw e;\r\n    }\r\n  };\r\n}\r\nvar mylib = {\r\n  provide: function (name, fn) {\r\n    \/\/ use 'guard' to wrap the function in the error handler \r\n    this[name] = guard(fn);\r\n  }\r\n};<\/pre>\n<p>In addition to the public interface, we instrument all entry points &#8212; including those executed via <em>setTimeout<\/em>\/<em>setInterval;<\/em> event handlers such as <em>onclick<\/em> or <em>onmessage;<\/em> and callbacks used with JSONP or XMLHttpRequest. Having a <em>guard<\/em> function makes this easy. We also pass the name of the entry point to the guard function, something that allows us to log the error, the entry point that eventually led to it, and its arguments. This makes it easy for us to reproduce issues, or at least to narrow down the possible causes.<\/p>\n<h2>Managed errors<\/h2>\n<p>The above instrumentation catches all errors that are thrown when executing &#8211; but what if there are errors that we actually want to <em>not<\/em> catch, like an error due to assertions made on passed arguments? These are clearly errors that we either don&#8217;t want to catch\/log, or at least want to treat differently. The solution we have chosen is to simply define our own error type that we use when throwing in a managed way, and then check for this in the <em>catch<\/em> block:<\/p>\n<pre>var ManagedError = function (message) {\r\n    Error.prototype.constructor.apply(this, arguments);\r\n    this.message = message;\r\n  };\r\nManagedError.prototype = new Error();\r\n\r\nfunction guard(fn) {\r\n  return function () {\r\n    try {\r\n      return fn.apply(this, arguments);\r\n    } catch (e) {\r\n      if (e instanceof ManagedError) {\r\n        \/\/ re-throw immediately \r\n        throw e;\r\n      }\r\n      \/\/ log error \r\n      ..\r\n      \/\/ re-throw to halt execution \r\n      throw e;\r\n    }\r\n  };\r\n}\r\n..\r\nmylib.provide('foo', function ( \/*..*\/ ) {\r\n  ..\r\n  throw new ManagedError('Invalid argument');\r\n});<\/pre>\n<p>With this approach, managed errors are re-thrown to the calling code, while unmanaged ones are captured and logged.<\/p>\n<h2>Calling external functions<\/h2>\n<p>The JS SDK has an event mechanism, and many of the exposed functions accept a callback argument that the SDK will invoke at some point. But this can easily be a source of false positives if any of these contain errors, so how do we solve this? Again, the conventional way of doing this is to explicitly wrap each invocation in a <em>try\/catch<\/em> block, but this can easily become unwieldy. Instead, we simply wrap all such functions when they pass through the initial <em>guard<\/em> function:<\/p>\n<pre>\/\/ Helper function for recursively wrapping functions \r\nfunction wrap(fn, value) {\r\n  \/\/ not all 'function's are actually functions! \r\n  if (typeof value === 'function' &amp;&amp; \/^function\/.test(value.toString())) {\r\n    return fn(value);\r\n  } else if (typeof value === 'object' &amp;&amp; value !== null) {\r\n    for (var key in value) if (value.hasOwnProperty(key)) {\r\n      value[key] = wrap(fn, value[key]);\r\n    };\r\n  }\r\n  return value;\r\n}\r\n\r\nfunction unguard(fn) {\r\n  return function () {\r\n    try {\r\n      return fn.apply(this, arguments);\r\n    } catch (e) {\r\n      \/\/ surface the error  \r\n      setTimeout(function () {\r\n        throw e;\r\n      }, 0);\r\n    }\r\n  };\r\n}\r\nfunction guard(fn) {\r\n  return function () {\r\n    \/\/ capture the arguments and unguard any functions \r\n    var args = Array.prototype.slice.call(arguments).map(function (arg) {\r\n      return wrap(unguard, arg);\r\n    });\r\n    try {\r\n      return fn.apply(this, args);\r\n    } catch (e) {\r\n      if (e instanceof ManagedError) {\r\n        throw e;\r\n      }\r\n      \/\/ log error \r\n      ..\r\n      \/\/ re-throw to halt execution \r\n      throw e;\r\n    }\r\n  };\r\n}<\/pre>\n<h2>Returning functions to external code<\/h2>\n<p>The last example that we&#8217;re going to cover here is the case where our functions actually <em>return<\/em> functions, or objects with function members. These represent an entry point to our code and we also want to guard these. Luckily, this can be done by simply wrapping the response value using the same pattern as above:<\/p>\n<pre>function guard(fn) {\r\n  return function () {\r\n    \/\/ capture the arguments and unguard any functions \r\n    var args = Array.prototype.slice.call(arguments).map(function (arg) {\r\n      return wrap(unguard, arg);\r\n    });\r\n    try {\r\n      return wrap(guard, fn.apply(this, args));\r\n    } catch (e) {\r\n      if (e instanceof ManagedError) {\r\n        throw e;\r\n      }\r\n      \/\/ log error \r\n      ..\r\n      \/\/ re-throw to halt execution \r\n      throw e;\r\n    }\r\n  };\r\n}<\/pre>\n<h2>Differentiating between internal and external callers<\/h2>\n<p>Some of you might have noticed one problem with our code so far: It doesn&#8217;t differentiate between internal and external callers. After all, it&#8217;s not uncommon for library code to call into other functions of the same library, is it? As it is now, <em>all<\/em> functions will effectively be wrapped, causing both an overhead in terms of function calls and errors in the reporting, as each function in the call chain will result in the error being logged. The solution? Simply create two <em>views<\/em> of our library, one to be used internally and one to be exported:<\/p>\n<pre>var mylib = (function () {\r\n  \/\/ object that will be exported to external callers \r\n  var public = {};\r\n  \/\/ object that will be used by internal callers \r\n  var mylib = {\r\n    \/\/ this will naively create new properties on our mylib object \r\n    provide: function (name, fn) {\r\n      this[name] = fn;\r\n      \/\/ use 'guard' to wrap the function in the error handler  \r\n      \/\/ for external use \r\n      public[name] = guard(fn);\r\n    }\r\n  };\r\n  ..\r\n  return public;\r\n})();<\/pre>\n<p>All callers defined inside the main closure will now be referencing the <em>internal<\/em> version of <em>mylib,<\/em> while external callers will be referencing the <em>public<\/em> version. An added side effect of this is that modifications made externally &#8212; such as someone replacing a function on the external object (so-called monkey patching) &#8212; do not have any effect on the internal code. Whether this is good or bad is entirely up to you, but from experience we have seen that monkey patches often change expected behavior and can quickly become misaligned with the rest of the code (causing more issues that they fix). We&#8217;ve also found that actively monitoring errors through code such as this reduces the need for such patches.<\/p>\n<p><em>(Since first writing this post, the JS SDK has been migrated to use only CommonJS internally, so we no longer rely on this separation)<\/em><\/p>\n<h2>Summary<\/h2>\n<p>We are continuously working on improving the JS SDK, and one of the key properties that we strive for is for it to be able to gracefully handle any error condition, so as to not disrupt the execution of your app. Having insights into the errors that are occurring on real third-party sites are of immense value and lets us quickly react to new issues being introduced, as well as fix old, but rarely seen, ones.<\/p>\n<p>If you want to see the full example created in this post in action, then you can find it in this <a href=\"http:\/\/jsfiddle.net\/2FU3J\/2\/\">jsFiddle<\/a> example &#8211; check the developer console for the output!<\/p>\n<p><em><a href=\"https:\/\/www.facebook.com\/oyvind.kinsey\">Sean Kinsey<\/a> is an engineer on the Platform team<\/em>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>For the next few weeks we will be exploring the internal details of our JavaScript SDK in a series of posts. Our hope is that this will help developers debug any issues with our SDK and give us an opportunity to outline some cool best practices for JavaScript libraries. In this post, we&#8217;re going to [&#8230;]<\/p>\n<p><a class=\"btn btn-secondary understrap-read-more-link\" href=\"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/\">Read More&#8230;<\/a><\/p>\n","protected":false},"author":12,"featured_media":11922,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[66],"tags":[136,112,137,129],"coauthors":[1222],"class_list":["post-5862","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developer-tools","tag-frontend","tag-infra","tag-javascript","tag-platform"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v19.3 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Under the Hood: The JavaScript SDK - error handling - Engineering at Meta<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"\u00d8yvind Sean Kinsey\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/2012\\\/11\\\/01\\\/developer-tools\\\/under-the-hood-the-javascript-sdk-error-handling\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/2012\\\/11\\\/01\\\/developer-tools\\\/under-the-hood-the-javascript-sdk-error-handling\\\/\"},\"author\":{\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/2012\\\/11\\\/01\\\/developer-tools\\\/under-the-hood-the-javascript-sdk-error-handling\\\/#author\",\"name\":\"\u00d8yvind Sean Kinsey\"},\"headline\":\"Under the Hood: The JavaScript SDK &#8211; error handling\",\"datePublished\":\"2012-11-01T17:45:32+00:00\",\"dateModified\":\"2018-12-13T00:05:25+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/2012\\\/11\\\/01\\\/developer-tools\\\/under-the-hood-the-javascript-sdk-error-handling\\\/\"},\"wordCount\":954,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/2012\\\/11\\\/01\\\/developer-tools\\\/under-the-hood-the-javascript-sdk-error-handling\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/engineering.fb.com\\\/wp-content\\\/uploads\\\/2012\\\/11\\\/1_zWhOGf_PgX0nRTLZLmFpGg.png\",\"keywords\":[\"Front End\",\"Infra\",\"JavaScript\",\"Platform\"],\"articleSection\":[\"DevInfra\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/engineering.fb.com\\\/2012\\\/11\\\/01\\\/developer-tools\\\/under-the-hood-the-javascript-sdk-error-handling\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/2012\\\/11\\\/01\\\/developer-tools\\\/under-the-hood-the-javascript-sdk-error-handling\\\/\",\"url\":\"https:\\\/\\\/engineering.fb.com\\\/2012\\\/11\\\/01\\\/developer-tools\\\/under-the-hood-the-javascript-sdk-error-handling\\\/\",\"name\":\"Under the Hood: The JavaScript SDK - error handling - Engineering at Meta\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/2012\\\/11\\\/01\\\/developer-tools\\\/under-the-hood-the-javascript-sdk-error-handling\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/2012\\\/11\\\/01\\\/developer-tools\\\/under-the-hood-the-javascript-sdk-error-handling\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/engineering.fb.com\\\/wp-content\\\/uploads\\\/2012\\\/11\\\/1_zWhOGf_PgX0nRTLZLmFpGg.png\",\"datePublished\":\"2012-11-01T17:45:32+00:00\",\"dateModified\":\"2018-12-13T00:05:25+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/2012\\\/11\\\/01\\\/developer-tools\\\/under-the-hood-the-javascript-sdk-error-handling\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/engineering.fb.com\\\/2012\\\/11\\\/01\\\/developer-tools\\\/under-the-hood-the-javascript-sdk-error-handling\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/2012\\\/11\\\/01\\\/developer-tools\\\/under-the-hood-the-javascript-sdk-error-handling\\\/#primaryimage\",\"url\":\"https:\\\/\\\/engineering.fb.com\\\/wp-content\\\/uploads\\\/2012\\\/11\\\/1_zWhOGf_PgX0nRTLZLmFpGg.png\",\"contentUrl\":\"https:\\\/\\\/engineering.fb.com\\\/wp-content\\\/uploads\\\/2012\\\/11\\\/1_zWhOGf_PgX0nRTLZLmFpGg.png\",\"width\":1563,\"height\":879},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/2012\\\/11\\\/01\\\/developer-tools\\\/under-the-hood-the-javascript-sdk-error-handling\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/engineering.fb.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Under the Hood: The JavaScript SDK &#8211; error handling\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/#website\",\"url\":\"https:\\\/\\\/engineering.fb.com\\\/\",\"name\":\"Engineering at Meta\",\"description\":\"Engineering at Meta Blog\",\"publisher\":{\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/engineering.fb.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/#organization\",\"name\":\"Meta\",\"url\":\"https:\\\/\\\/engineering.fb.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/engineering.fb.com\\\/wp-content\\\/uploads\\\/2023\\\/08\\\/Meta_lockup_positive-primary_RGB.jpg\",\"contentUrl\":\"https:\\\/\\\/engineering.fb.com\\\/wp-content\\\/uploads\\\/2023\\\/08\\\/Meta_lockup_positive-primary_RGB.jpg\",\"width\":29011,\"height\":12501,\"caption\":\"Meta\"},\"image\":{\"@id\":\"https:\\\/\\\/engineering.fb.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/Engineering\\\/\",\"https:\\\/\\\/x.com\\\/fb_engineering\"]},[]]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Under the Hood: The JavaScript SDK - error handling - Engineering at Meta","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/","twitter_misc":{"Written by":"\u00d8yvind Sean Kinsey","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/#article","isPartOf":{"@id":"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/"},"author":{"@id":"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/#author","name":"\u00d8yvind Sean Kinsey"},"headline":"Under the Hood: The JavaScript SDK &#8211; error handling","datePublished":"2012-11-01T17:45:32+00:00","dateModified":"2018-12-13T00:05:25+00:00","mainEntityOfPage":{"@id":"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/"},"wordCount":954,"commentCount":0,"publisher":{"@id":"https:\/\/engineering.fb.com\/#organization"},"image":{"@id":"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/#primaryimage"},"thumbnailUrl":"https:\/\/engineering.fb.com\/wp-content\/uploads\/2012\/11\/1_zWhOGf_PgX0nRTLZLmFpGg.png","keywords":["Front End","Infra","JavaScript","Platform"],"articleSection":["DevInfra"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/","url":"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/","name":"Under the Hood: The JavaScript SDK - error handling - Engineering at Meta","isPartOf":{"@id":"https:\/\/engineering.fb.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/#primaryimage"},"image":{"@id":"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/#primaryimage"},"thumbnailUrl":"https:\/\/engineering.fb.com\/wp-content\/uploads\/2012\/11\/1_zWhOGf_PgX0nRTLZLmFpGg.png","datePublished":"2012-11-01T17:45:32+00:00","dateModified":"2018-12-13T00:05:25+00:00","breadcrumb":{"@id":"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/#primaryimage","url":"https:\/\/engineering.fb.com\/wp-content\/uploads\/2012\/11\/1_zWhOGf_PgX0nRTLZLmFpGg.png","contentUrl":"https:\/\/engineering.fb.com\/wp-content\/uploads\/2012\/11\/1_zWhOGf_PgX0nRTLZLmFpGg.png","width":1563,"height":879},{"@type":"BreadcrumbList","@id":"https:\/\/engineering.fb.com\/2012\/11\/01\/developer-tools\/under-the-hood-the-javascript-sdk-error-handling\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/engineering.fb.com\/"},{"@type":"ListItem","position":2,"name":"Under the Hood: The JavaScript SDK &#8211; error handling"}]},{"@type":"WebSite","@id":"https:\/\/engineering.fb.com\/#website","url":"https:\/\/engineering.fb.com\/","name":"Engineering at Meta","description":"Engineering at Meta Blog","publisher":{"@id":"https:\/\/engineering.fb.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/engineering.fb.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/engineering.fb.com\/#organization","name":"Meta","url":"https:\/\/engineering.fb.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/engineering.fb.com\/#\/schema\/logo\/image\/","url":"https:\/\/engineering.fb.com\/wp-content\/uploads\/2023\/08\/Meta_lockup_positive-primary_RGB.jpg","contentUrl":"https:\/\/engineering.fb.com\/wp-content\/uploads\/2023\/08\/Meta_lockup_positive-primary_RGB.jpg","width":29011,"height":12501,"caption":"Meta"},"image":{"@id":"https:\/\/engineering.fb.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Engineering\/","https:\/\/x.com\/fb_engineering"]},[]]}},"jetpack_featured_media_url":"https:\/\/engineering.fb.com\/wp-content\/uploads\/2012\/11\/1_zWhOGf_PgX0nRTLZLmFpGg.png","jetpack_shortlink":"https:\/\/wp.me\/pa0Lhq-1wy","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/engineering.fb.com\/wp-json\/wp\/v2\/posts\/5862","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/engineering.fb.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/engineering.fb.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/engineering.fb.com\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/engineering.fb.com\/wp-json\/wp\/v2\/comments?post=5862"}],"version-history":[{"count":2,"href":"https:\/\/engineering.fb.com\/wp-json\/wp\/v2\/posts\/5862\/revisions"}],"predecessor-version":[{"id":11923,"href":"https:\/\/engineering.fb.com\/wp-json\/wp\/v2\/posts\/5862\/revisions\/11923"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/engineering.fb.com\/wp-json\/wp\/v2\/media\/11922"}],"wp:attachment":[{"href":"https:\/\/engineering.fb.com\/wp-json\/wp\/v2\/media?parent=5862"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/engineering.fb.com\/wp-json\/wp\/v2\/categories?post=5862"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/engineering.fb.com\/wp-json\/wp\/v2\/tags?post=5862"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/engineering.fb.com\/wp-json\/wp\/v2\/coauthors?post=5862"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}