<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Matheus Lima</title>
    <description>The latest articles on DEV Community by Matheus Lima (@matheuscaldas1).</description>
    <link>https://dev.to/matheuscaldas1</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1110107%2Fe69af167-9b95-4ad1-9b1a-dba296852ce1.jpeg</url>
      <title>DEV Community: Matheus Lima</title>
      <link>https://dev.to/matheuscaldas1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/matheuscaldas1"/>
    <language>en</language>
    <item>
      <title>How to Stop LLM Hallucinations from Crashing Your React UI (Fixing AI_JSONParseError)</title>
      <dc:creator>Matheus Lima</dc:creator>
      <pubDate>Thu, 02 Apr 2026 01:03:54 +0000</pubDate>
      <link>https://dev.to/matheuscaldas1/how-to-stop-llm-hallucinations-from-crashing-your-react-ui-fixing-aijsonparseerror-38a8</link>
      <guid>https://dev.to/matheuscaldas1/how-to-stop-llm-hallucinations-from-crashing-your-react-ui-fixing-aijsonparseerror-38a8</guid>
      <description>&lt;p&gt;Building Generative UIs with tools like the Vercel AI SDK is incredibly powerful until it suddenly isn't.&lt;/p&gt;

&lt;p&gt;ou’ve set up your tool calls, your streaming is incredibly fast, and it works flawlessly 99% of the time. But LLMs are inherently non-deterministic. Eventually, the model will drop a quote mark in the middle of a JSON stream, or decide to wrap its raw output inside a markdown block (&lt;code&gt;json&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;When that happens, your application doesn't just show a typo. It throws a synchronous parsing error. And in React, an unhandled error means one thing: The White Screen of Death (WSOD).&lt;/p&gt;

&lt;p&gt;If you look at the Vercel AI SDK GitHub repository, you'll see developers fighting this in the trenches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/vercel/ai/issues/13514" rel="noopener noreferrer"&gt;Issue #13514&lt;/a&gt;: Tool streaming causes malformed JSON.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/vercel/ai/issues/4906" rel="noopener noreferrer"&gt;Issue #4906&lt;/a&gt;: The LLM randomly outputs Markdown blocks instead of pure objects, crashing the preflight parsing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/vercel/ai/issues/1167" rel="noopener noreferrer"&gt;Issue #1167&lt;/a&gt;: RSC stream aborts completely unmount the React tree.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's look at why standard React tools fail here, and how to elegantly quarantine these hallucinations.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trap of Standard Error Boundaries
&lt;/h2&gt;

&lt;p&gt;When a standard React component throws an error, the official advice is to wrap it in an &lt;code&gt;&amp;lt;ErrorBoundary&amp;gt;&lt;/code&gt;. But Generative UI is different.&lt;/p&gt;

&lt;p&gt;If you are building an AI Chat interface, the tool component (let's say, a financial chart generated by the LLM) is a child of the message list. If the LLM hallucinates the schema (e.g., returns a string instead of an array) and your chart component tries to &lt;code&gt;.map()&lt;/code&gt; over it, it crashes.&lt;/p&gt;

&lt;p&gt;If you rely on a generic Error Boundary higher up in your tree, React unmounts the entire chat history to show the fallback UI. Your user just lost their entire 20-minute context because the AI forgot a comma. That is unacceptable UX.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Ugly Fix
&lt;/h2&gt;

&lt;p&gt;To prevent this, developers end up writing massive, defensive &lt;code&gt;try/catch&lt;/code&gt; blocks inside every single component, or attempting to write regex-based "JSON cleaners" to sanitize strings mid-stream. It pollutes your codebase with error-handling logic that obscures the actual business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Elegant Fix: Quarantining Generative UI
&lt;/h2&gt;

&lt;p&gt;We need a surgical approach: a boundary specifically designed for the unpredictable nature of AI payloads. That's why I built &lt;code&gt;&amp;lt;AIBoundary /&amp;gt;&lt;/code&gt; as part of the CogniCatch open-source library.&lt;/p&gt;

&lt;p&gt;Instead of generic error handling, &lt;code&gt;AIBoundary&lt;/code&gt; creates an isolated quarantine zone around your GenUI components. If the LLM hallucinates or spits out malformed JSON, the boundary intercepts the crash, keeps the rest of the application (like the chat history) perfectly intact, and gracefully handles the failure in-place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to use it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, install the package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @cognicatch/react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, simply wrap the component responsible for rendering the LLM's output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AIBoundary&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@cognicatch/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FinancialChart&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/FinancialChart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ChatMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;toolInvocation&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// If toolInvocation.args comes back malformed,&lt;/span&gt;
  &lt;span class="c1"&gt;// FinancialChart will crash. AIBoundary protects the app.&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AIBoundary&lt;/span&gt;
      &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"manual"&lt;/span&gt;
      &lt;span class="na"&gt;showRawData&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
      &lt;span class="na"&gt;rawPayload&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toolInvocation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
      &lt;span class="na"&gt;onRecover&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;triggerRetryInChatStream&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FinancialChart&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toolInvocation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;AIBoundary&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What happens under the hood?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Isolation: If FinancialChart throws TypeError: undefined is not a function because of a schema hallucination, the error is stopped dead in its tracks. The parent component (the chat window) doesn't even flinch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Contextual Fallback: Instead of a generic "Something went wrong" message, CogniCatch displays an elegant, purpose-built Generative UI fallback.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recovery: By providing the rawPayload, developers (or users, depending on your setup) can actually see the hallucinated output, and the onRecover action allows you to instantly trigger a retry to the LLM without reloading the page.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Open-Source vs. Auto Mode&lt;/p&gt;

&lt;p&gt;CogniCatch is an &lt;strong&gt;open-core&lt;/strong&gt; project.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;mode="manual"&lt;/code&gt; (open-source) is completely free and runs locally. It isolates the crash, prevents the White Screen of Death, and exposes the &lt;code&gt;rawPayload&lt;/code&gt; so your users (or you) can see the hallucinated output, allowing them to hit "Try Again" via the &lt;code&gt;onRecover&lt;/code&gt; callback.&lt;/p&gt;

&lt;p&gt;But I also built a &lt;strong&gt;Pro Tier (&lt;code&gt;mode="auto"&lt;/code&gt;)&lt;/strong&gt; for a fully hands-off UX:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Automatically translate the error empathetic message into the user's native browser language.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Visually parse and beautifully format the malformed JSON so developers and users can easily read what went wrong.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://cognicatch.dev/" rel="noopener noreferrer"&gt;Join the Early Adopter Waitlist at cognicatch.dev&lt;/a&gt;&lt;/em&gt; (Early birds get 50% off the Pro tier for the first 6 months!).&lt;/p&gt;

&lt;h2&gt;
  
  
  Stop letting LLMs dictate your app's stability
&lt;/h2&gt;

&lt;p&gt;We shouldn't let the non-deterministic nature of AI degrade the deterministic reliability of our React applications. By treating LLM outputs as highly volatile external data and wrapping them in specialized boundaries, you guarantee that an AI's mistake never becomes a user's frustration.&lt;/p&gt;

&lt;p&gt;If you are tired of building AI wrappers that crash on unpredictable streams, give &lt;a href="https://github.com/cognicatch/react" rel="noopener noreferrer"&gt;CogniCatch&lt;/a&gt; a try. It’s open-source, beautifully styled out of the box, and respects your telemetry.&lt;/p&gt;

&lt;p&gt;Happy (and safe) prompting!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;(Note: If you need to silently log these hallucinations to Sentry or Datadog without breaking the UI, the package also exposes an onError callback designed specifically to avoid blinding your observability tools. &lt;a href="https://dev.to/matheuscaldas1/how-to-catch-react-errors-for-your-users-without-blinding-your-sentry-logs-288p"&gt;You can read my previous article about that here&lt;/a&gt;).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>react</category>
      <category>ux</category>
    </item>
    <item>
      <title>How to catch React errors for your users without blinding your Sentry logs</title>
      <dc:creator>Matheus Lima</dc:creator>
      <pubDate>Thu, 26 Mar 2026 19:38:38 +0000</pubDate>
      <link>https://dev.to/matheuscaldas1/how-to-catch-react-errors-for-your-users-without-blinding-your-sentry-logs-288p</link>
      <guid>https://dev.to/matheuscaldas1/how-to-catch-react-errors-for-your-users-without-blinding-your-sentry-logs-288p</guid>
      <description>&lt;p&gt;Every React developer fears the "White Screen of Death". When a single component throws an unhandled error, React unmounts the entire component tree, leaving the user staring at a blank page.&lt;/p&gt;

&lt;p&gt;To fix this, we use Error Boundaries. But there is a hidden trap that catches even senior teams: if you catch an error locally to show a fallback UI, the error stops bubbling up. Suddenly, your app is failing in production, users are seeing a generic "Something went wrong" message, and your Sentry dashboard is completely silent. You just traded a UX nightmare for an observability nightmare.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Traditional (and Messy) Approach
&lt;/h2&gt;

&lt;p&gt;When we write custom Error Boundaries from scratch, we usually end up mixing UI logic with telemetry logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The typical, messy approach&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomErrorBoundary&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;hasError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;componentDidCatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;errorInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;hasError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="c1"&gt;// If a dev forgets to add this line, Sentry goes blind!&lt;/span&gt;
    &lt;span class="nx"&gt;Sentry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;captureException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;errorInfo&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ugly-red-box&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Something&lt;/span&gt; &lt;span class="nx"&gt;went&lt;/span&gt; &lt;span class="nx"&gt;wrong&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This scales poorly. Developers often forget to wire up the logging service when quickly wrapping a new component, and you end up rewriting fallback UIs (toasts, banners, modals) for every different part of your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Separation of Concerns
&lt;/h2&gt;

&lt;p&gt;Good Developer Experience (DX) is about combining the right tools for the right jobs. Sentry is incredible at backend telemetry and tracking bugs. But it shouldn't be responsible for your frontend UI.&lt;/p&gt;

&lt;p&gt;To solve this, I built CogniCatch, an open-source React wrapper that standardizes Graceful UI Degradation. Instead of a blank screen, it replaces the broken component with standardized, empathetic UI notifications.&lt;/p&gt;

&lt;p&gt;In my latest release (v1.1.6), I introduced a fail-safe onError callback specifically designed to solve the "swallowed error" problem.&lt;/p&gt;

&lt;p&gt;Here is how you pair CogniCatch with Sentry to get the perfect architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Sentry&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@sentry/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AdaptiveErrorBoundary&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@cognicatch/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;CheckoutFlow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AdaptiveErrorBoundary&lt;/span&gt; 
      &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;manual&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;severity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Payment Failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;We couldn't process your card right now. Please try again.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="c1"&gt;// The magic happens here: &lt;/span&gt;
      &lt;span class="c1"&gt;// The UI stays up, and Sentry gets the log silently.&lt;/span&gt;
      &lt;span class="nx"&gt;onError&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;errorInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Sentry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;captureException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;errorInfo&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PaymentForm&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/AdaptiveErrorBoundary&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Double Benefit
&lt;/h2&gt;

&lt;p&gt;By decoupling the UI degradation from the telemetry, everybody wins:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For the User (Perfect UX): Instead of a broken layout, they see a clean, localized banner (or toast) letting them know the payment failed. The rest of the application (sidebar, header, navigation) remains perfectly intact and interactive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For the Developer (Perfect DX): The onError callback runs safely in the background inside a hardened try/catch block. Sentry immediately lights up in your Slack channel with the exact stack trace and component tree. No silent failures.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it out
&lt;/h2&gt;

&lt;p&gt;I built CogniCatch open-source because I was tired of writing endless switch statements to map API errors and polluting my components with logger logic.&lt;/p&gt;

&lt;p&gt;If you want to stop losing telemetry while keeping your users happy, check out the repository and give it a try.&lt;/p&gt;

&lt;p&gt;⭐ &lt;a href="//github.com/CogniCatch/react"&gt;Star CogniCatch on GitHub&lt;/a&gt;&lt;br&gt;
 &lt;code&gt;npm install @cognicatch/react&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let Sentry handle the logs. Let CogniCatch handle the interface.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Let me know in the comments how your team currently handles React fallbacks alongside your observability stack!)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>ux</category>
    </item>
    <item>
      <title>Stop showing "Something went wrong" to your users. How I automated React error handling with AI</title>
      <dc:creator>Matheus Lima</dc:creator>
      <pubDate>Mon, 16 Mar 2026 13:52:20 +0000</pubDate>
      <link>https://dev.to/matheuscaldas1/stop-showing-something-went-wrong-to-your-users-how-i-automated-react-error-handling-with-ai-ma5</link>
      <guid>https://dev.to/matheuscaldas1/stop-showing-something-went-wrong-to-your-users-how-i-automated-react-error-handling-with-ai-ma5</guid>
      <description>&lt;p&gt;If you are a frontend or full-stack developer, you probably hate dealing with third-party API errors as much as I do.&lt;/p&gt;

&lt;p&gt;You are building a beautiful React, tanStack or Next.js application, everything is smooth, and then you have to integrate an external API. Suddenly, your network tab is full of unpredictable errors: 503 Service Unavailable, 429 Too Many Requests, CORS preflight failed, or some bizarre custom JSON error from a legacy system.&lt;/p&gt;

&lt;p&gt;You usually have two choices, and both of them suck:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The Exhausting Way: Write endless switch statements to map every single possible error code and translate them into human-readable messages. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Lazy Way: Wrap everything in a try/catch and show a generic "Oops, something went wrong. Please try again later" to your user.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I got tired of wasting hours tracking down delicate component errors and writing fallback UI copy. So, I built a tool to completely automate this.&lt;/p&gt;

&lt;p&gt;Meet &lt;strong&gt;CogniCatch&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://cognicatch.dev/" rel="noopener noreferrer"&gt;CogniCatch&lt;/a&gt; to be the ultimate time-saver for React developers. It's an Edge-native error analytics and UX platform that catches raw, ugly API errors and translates them into empathetic, actionable, and localized UI messages using AI.&lt;/p&gt;

&lt;p&gt;Instead of mapping 50 different error scenarios from a public API, you just wrap your risky calls or Error Boundaries with the CogniCatch SDK.&lt;/p&gt;

&lt;p&gt;How it saves you hours of work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;No more mapping 3rd-party errors: Whether the API fails because of a timeout, a rate limit, or a server crash, CogniCatch understands the context of the raw stack trace and generates a user-friendly explanation on the fly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automatic Localization: If your user speaks Portuguese, Spanish, or French, the AI automatically translates the recovery message without you having to touch an i18n JSON file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zero Jargon: It ensures your end-users never see words like "TCP Socket Hang up" or "Null pointer exception". It tells them exactly what happened in plain English (or their native language).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Under the Hood: Built for the Edge&lt;/p&gt;

&lt;p&gt;As engineers, we care about latency. An error handling tool cannot slow down your app.&lt;/p&gt;

&lt;p&gt;I built the CogniCatch infrastructure to run entirely on the Edge. Here is the stack that makes it execute in milliseconds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare Workers &amp;amp; Pages:&lt;/strong&gt; For global, zero-cold-start execution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supabase (PostgreSQL) + Drizzle ORM:&lt;/strong&gt; We bypassed traditional transaction pooling (PgBouncer) issues on the Edge, connecting directly to the database to ensure sub-500ms query times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upstash Redis:&lt;/strong&gt; Distributed rate-limiting to protect the ingestion API from DDoS or abuse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI (GPT-4o-mini):&lt;/strong&gt; Strictly configured to return structured JSONs with title, description, and severity, while a custom PII Shielding algorithm ensures no sensitive user data ever touches the LLM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stop writing generic fallbacks&lt;/p&gt;

&lt;p&gt;If you want to save time, keep your codebase clean from endless error-mapping files, and actually provide a great UX when things break, give it a try.&lt;/p&gt;

&lt;p&gt;I'm currently opening early access to developers and provisioning the infrastructure.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://cognicatch.dev/" rel="noopener noreferrer"&gt;Join the Early Adopter Waitlist at cognicatch.dev&lt;/a&gt; (Early birds get 50% off the Pro tier for the first 6 months!).&lt;/p&gt;

&lt;p&gt;Let me know in the comments: what is the worst/most bizarre third-party API error you've ever had to handle in the frontend?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>showdev</category>
      <category>react</category>
    </item>
  </channel>
</rss>
