PageSourceSearch

https://www.sam.today/_next/static/chunks/pages/blog/one-trick-debugger-fc602bdfb066ac54.js

js sam.today collected 2026-10-03 20:26:20 UTC 7,968 bytes, 1 lines download raw bytes

1(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[4036],{7228:function(e,n,s){(window.__NEXT_P=window.__NEXT_P||[]).push(["/blog/one-trick-debugger",function(){return s(7579)}])},7579:function(e,n,s){"use strict";s.r(n),s.d(n,{__N_SSG:function(){return o},meta:function(){return a}});var t=s(5893),i=s(1151),r=s(2256),o=!0;let a={title:"“One Trick” to Save Time Integrating with Buggy Proprietary Apps",summary:"Finding a use for the browser dev tools that I never expected",published:"18 Apr 2025",heroImage:"/images/blog/214/hero.webp",openGraphImage:"/images/blog/214/opengraph.png",heroTheme:"lightOnDark",order:214},l=e=>(0,t.jsx)(r.j0,Object.assign({meta:a},e));function h(e){let n=Object.assign({p:"p",code:"code",em:"em",h3:"h3",a:"a",img:"img",ul:"ul",li:"li",strong:"strong",ol:"ol"},(0,i.ah)(),e.components);return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["Maybe I’m old-fashioned, but I rarely use a debugger when programming. Usually, chucking in some ",(0,t.jsx)(n.code,{children:"print"})," statements to test my assumptions does the job."]}),"\n",(0,t.jsxs)(n.p,{children:["I’ve recently found a surprising use for this dev tool; ",(0,t.jsx)(n.em,{children:"debugging other people’s code. In particular, 2 checkboxes"})," are usually enough to find exactly what I’m looking for, even in megabytes of minified, proprietary code. This technique is simpler than I thought, so I’ll share it below:"]}),"\n",(0,t.jsx)(n.h3,{children:"Setting the scene"}),"\n",(0,t.jsxs)(n.p,{children:["I first used this while building Webflow integrations at ",(0,t.jsx)(n.a,{href:"https://www.relume.io",children:"Relume"}),". Our Webflow features mostly worked via the clipboard; we’d write the data in Webflow’s internal, undocumented format, and then the user would paste it into the Webflow app. Sometimes, our data would crash Webflow’s frontend, but it wasn’t clear why."]}),"\n",(0,t.jsx)(n.p,{children:"That scenario felt specific to Relume, so I was reluctant to share it. However, recently I ended up using the same technique in a wildly different situation."}),"\n",(0,t.jsxs)(n.p,{children:["For ",(0,t.jsx)(n.a,{href:"https://www.xintra.org/",children:"XINTRA Labs"}),", I was building a Microsoft Entra ID SAML Federation Provider, whatever that means. As part of that, I needed to upload an SAML-formatted XML file to the Entra dashboard. But when I uploaded the file, all I got was a generic error message:"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:"/images/blog/214/image.webp",alt:"Entra error message"})}),"\n",(0,t.jsx)(n.p,{children:"Initially, I opened the browser dev tools and resubmitted the file. I thought the parsing would be done by the backend, but saw no network request made. That left only 1 option; the Entra ID frontend parsed the file. A frontend error calls for the JS debugger:"}),"\n",(0,t.jsx)(n.h3,{children:"Finding a bug in somebody else’s frontend"}),"\n",(0,t.jsx)(n.p,{children:"So I was in this situation:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"I could reproduce a bug reliably (uploading a file)"}),"\n",(0,t.jsx)(n.li,{children:"But I didn’t get a helpful error"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["To reveal the secrets, I opened my browser’s ",(0,t.jsx)(n.strong,{children:"Debugger"})," (caused the “",(0,t.jsx)(n.em,{children:"Sources"}),"” tab in Chrome) and checked 2 options: ",(0,t.jsx)(n.strong,{children:"Pause on Uncaught Exceptions"})," and ",(0,t.jsx)(n.strong,{children:"Pause on Caught Exceptions"}),"."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:"/images/blog/214/checkboxes.webp",alt:"Chrome DevTools checkboxes"})}),"\n",(0,t.jsx)(n.p,{children:"After reproducing the bug, the debugger paused at exactly the code that was causing the error:"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:"/images/blog/214/image%201.webp",alt:"Chrome DevTools debugger pause"})}),"\n",(0,t.jsx)(n.p,{children:"Here, I can see 3 critical things:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["The step where the error originates (finding ",(0,t.jsx)(n.code,{children:"EntityDescriptor"}
1)," XML element)"]}),"\n",(0,t.jsxs)(n.li,{children:["The variables of interest (",(0,t.jsx)(n.code,{children:"t"})," - the parsed XML file)"]}),"\n",(0,t.jsxs)(n.li,{children:["Using Chrome’s console, I can poke further in the variables (running ",(0,t.jsx)(n.code,{children:"t.childNodes[2].nodeName"})," to verify that my XML file’s ",(0,t.jsx)(n.code,{children:"EntityDescriptor"})," is in fact loaded)"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:"/images/blog/214/image%202.webp",alt:"Chrome DevTools console usage"})}),"\n",(0,t.jsxs)(n.p,{children:["In this case, the error is obvious. The Entra portal’s XML parsing does not handle XML namespaces irrespective of aliases. To workaround Entra’s issue, I needed to write my XML file with specific namespace aliases (",(0,t.jsx)(n.code,{children:"md:"})," instead of ",(0,t.jsx)(n.code,{children:"ns0:"}),")."]}),"\n",(0,t.jsx)(n.p,{children:"Spending a few minutes with the debugger saved a lot of time staring at non-existent documentation or even submitting a support request."}),"\n",(0,t.jsx)(n.h3,{children:"What about bigger apps?"}),"\n",(0,t.jsx)(n.p,{children:"The bug isn’t always this obvious. For instance, when investigating Webflow crashes during my work at Relume, I had to undertake some additional steps:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Parts of Webflow’s coded follow the idiom of “Ask Forgiveness, Not Permission.” So my debugger would repeatedly pause in code that used exceptions for control flow; pausing before I even started reproducing the bug. That is easily fixed by right clicking the line number and selecting “",(0,t.jsx)(n.em,{children:"Never Pause Here"}),"” then pressing ",(0,t.jsx)(n.code,{children:"F8"})," or “",(0,t.jsx)(n.em,{children:"Resume script execution"}),"”."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:"/images/blog/214/image4.webp",alt:"Chrome DevTools Never Pause Here"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Webflow’s code is minified. Make sure that “",(0,t.jsx)(n.em,{children:"Automatically pretify minified sources”"})," is enabled. Chrome will prompt you the first time, but you can change the option in the DevTool’s settings later too:"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:"/images/blog/214/image%203.webp",alt:"Chrome DevTools settings"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Webflow’s code was more abstract than Entra portal. The code where the debugger paused was less informative about the issue. However, looking at the ",(0,t.jsx)(n.em,{children:"Local"})," Variables in the ",(0,t.jsx)(n.em,{children:"Scope"})," panel, I could see a UUID. Cross-referencing with my input, it was clear that I’d accidentally created a cycle in what was supposed to be a tree:"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:"/images/blog/214/compare.webp",alt:"ChromeDev Tools scope compared to JSON doc"})}),"\n",(0,t.jsx)(n.h3,{children:"Conclusion"}),"\n",(0,t.jsxs)(n.p,{children:["Next time you’re battling some baffling behaviour on a web app, I hope this strategy can help you get to the root cause. Try using ",(0,t.jsx)(n.em,{children:"Pause on Caught Exceptions"})," to track down errors where the web app’s UI is hiding information you need to fix it."]}),"\n",(0,t.jsx)(n.p,{children:"Do you have other tips & tricks for building integrations with spottily documented services? If so, I’d love to hear them below."}),"\n"]})}n.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return(0,t.jsx)(l,Object.assign({},e,{children:(0,t.jsx)(h,e)}))}}},function(e){e.O(0,[8695,2256,9774,2888,179],function(){return e(e.s=7228)}),_N_E=e.O()}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.