<?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: Alkhassim Lawal Umar</title>
    <description>The latest articles on DEV Community by Alkhassim Lawal Umar (@alkhassim_lawalumar).</description>
    <link>https://dev.to/alkhassim_lawalumar</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3920788%2Fe001a120-bb7d-43a5-a707-19bfb576e419.jpg</url>
      <title>DEV Community: Alkhassim Lawal Umar</title>
      <link>https://dev.to/alkhassim_lawalumar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alkhassim_lawalumar"/>
    <language>en</language>
    <item>
      <title>The Sentry dashboard was empty for months — here's why (and the 2-line fix that mattered most)</title>
      <dc:creator>Alkhassim Lawal Umar</dc:creator>
      <pubDate>Mon, 27 Jul 2026 09:08:40 +0000</pubDate>
      <link>https://dev.to/alkhassim_lawalumar/the-sentry-dashboard-was-empty-for-months-heres-why-and-the-2-line-fix-that-mattered-most-1829</link>
      <guid>https://dev.to/alkhassim_lawalumar/the-sentry-dashboard-was-empty-for-months-heres-why-and-the-2-line-fix-that-mattered-most-1829</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/bugsmash"&gt;DEV's Summer Bug Smash: Clear the Lineup&lt;/a&gt; powered by &lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Overview
&lt;/h2&gt;

&lt;p&gt;This backend powers &lt;a href="https://kingxtech.name.ng/" rel="noopener noreferrer"&gt;K-XpertAI&lt;/a&gt;, the AI coding assistant at the center of &lt;a href="https://kingxtech.name.ng/" rel="noopener noreferrer"&gt;KingxTech&lt;/a&gt;'s developer-tools ecosystem — a chat-first assistant that turns a prompt into working code in a live artifact panel, with &lt;a href="https://kingxtech.name.ng/" rel="noopener noreferrer"&gt;SynthCode IDE&lt;/a&gt; as the editor you take it into next. The service in question is the Node/Express backend (internally &lt;code&gt;kx-neurocore&lt;/code&gt;) that routes every chat turn across multiple model providers — Claude, Gemini, GPT, and a free open-weights tier — while also handling credits, billing, chat history, GitHub push/import, and per-project file storage. It runs on Google Cloud Run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug Fix or Performance Improvement
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;TL;DR: Sentry had a valid DSN, was fully configured, and still saw nothing. Zero errors, zero transactions, for months. The DSN wasn't the problem — 18 routes silently never told it anything was wrong.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I went looking for why the dashboard was a ghost town, and traced it to one line of asymmetry in the code: &lt;strong&gt;only one route out of nineteen ever called &lt;code&gt;Sentry.captureException()&lt;/code&gt;.&lt;/strong&gt; Everything else — billing checkout, credit checks, chat sessions, chat history, GitHub push/import, project file reads/writes — caught its own errors and quietly did &lt;code&gt;console.error(...)&lt;/code&gt;, then returned a clean JSON error to the client. Functionally fine for the user. Invisible to Sentry.&lt;/p&gt;

&lt;p&gt;That's the dangerous kind of bug: nothing crashes, nothing 500s in a way anyone notices, the app "works." But the one signal that would have told me a Paystack checkout was failing, or a GitHub push was silently erroring for a specific user, never left &lt;code&gt;stdout&lt;/code&gt;. Whatever was actually breaking in production was a total blind spot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F47imp2sc11yp4zqxwl5y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F47imp2sc11yp4zqxwl5y.png" alt="Sentry showing NODE-1, the first issue ever recorded in this project, captured seconds after deploying the fix" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NODE-1 — the first issue ever recorded in this Sentry project, captured seconds after deploying the fix.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/KingzAlkhasim/Oauth-kingxtech/pull/1" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        fix: Sentry error reporting gap across API routes
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/KingzAlkhasim" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F113271137%3Fv%3D4" alt="KingzAlkhasim avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/KingzAlkhasim" rel="noopener noreferrer"&gt;KingzAlkhasim&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/KingzAlkhasim/Oauth-kingxtech/pull/1" rel="noopener noreferrer"&gt;&lt;time&gt;Jul 26, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Sentry was correctly configured with a valid DSN, but the project dashboard showed zero transactions and zero errors, even in production. Digging through the codebase, I found the actual cause: only one route (/api/ai/generate) called Sentry.captureException(). Every other route — 18 of them, covering billing, credits, sessions, chat history, GitHub integration, and project file operations — only did console.error(...). Errors on those routes were logged to stdout and then simply vanished; Sentry never saw them at all.&lt;/p&gt;
&lt;p&gt;This meant that whatever was actually breaking for real users — a failed Paystack checkout, a broken GitHub push, a corrupted session — was completely invisible in Sentry, no matter how well-configured the DSN was.&lt;/p&gt;
&lt;p&gt;My Improvements&lt;/p&gt;
&lt;p&gt;Rather than adding a one-off Sentry.captureException() call at each of the 18 sites individually, I centralized the fix:&lt;/p&gt;
&lt;p&gt;13 of the 18 routes already funneled their errors through a shared handleFsError() helper — I fixed the instrumentation gap there once, which covered all 13 in a single change.
The remaining 5 routes built their own status codes/messages, so I added a small reportError() helper with the same signature and reused it across those.
Both helpers use the identical await Sentry.flush(2000).catch(() =&amp;gt; {}) pattern that the one correctly-instrumented route already had — this matters specifically on Cloud Run, which freezes a container's CPU immediately after the HTTP response is sent. Sentry delivers events asynchronously in the background, so without an explicit flush before the response ends, a scaled-down instance can silently drop the event mid-delivery.
I also added a one-line startup log ([sentry] initialized / [sentry] disabled — SENTRY_DSN not set) — previously there was no way to tell from Cloud Run's logs whether Sentry had actually picked up the DSN on a given deploy.&lt;/p&gt;
&lt;p&gt;Typechecked clean against the existing tsconfig.json with no other behavior changes — every route still returns the same status codes and error messages to the client; the only difference is that unexpected errors now actually reach Sentry.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/KingzAlkhasim/Oauth-kingxtech/pull/1" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  My Improvements
&lt;/h2&gt;

&lt;p&gt;Instead of bolting &lt;code&gt;Sentry.captureException()&lt;/code&gt; onto all 18 catch blocks one by one, I collapsed the fix into two places:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;13 of the 18&lt;/strong&gt; already funneled through one shared &lt;code&gt;handleFsError()&lt;/code&gt; helper — fixing the gap there covered all 13 routes in a single change.&lt;/li&gt;
&lt;li&gt;The remaining &lt;strong&gt;5&lt;/strong&gt; built their own status codes and messages, so I extracted a small &lt;code&gt;reportError()&lt;/code&gt; helper with the same shape and swapped them over.&lt;/li&gt;
&lt;li&gt;Both helpers share the exact &lt;code&gt;await Sentry.flush(2000).catch(() =&amp;gt; {})&lt;/code&gt; pattern the one &lt;em&gt;correctly&lt;/em&gt;-instrumented route already had — and that flush isn't decorative. Cloud Run freezes a container's CPU the instant the HTTP response is sent. Sentry ships events asynchronously in the background, so a fire-and-forget &lt;code&gt;captureException()&lt;/code&gt; is racing against the container being frozen mid-delivery. Skip the flush, and even a &lt;em&gt;correctly called&lt;/em&gt; Sentry report can vanish.&lt;/li&gt;
&lt;li&gt;I also added one line at startup — &lt;code&gt;[sentry] initialized&lt;/code&gt; or &lt;code&gt;[sentry] disabled — SENTRY_DSN not set&lt;/code&gt; — because there was previously no way to tell from Cloud Run's logs whether Sentry had even picked up the DSN on a given deploy. The exact class of bug I'd just spent an afternoon hunting down would have taken thirty seconds to diagnose with that log line in place.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt; — every route silently swallowed its own errors:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleFsError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Response&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;unknown&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="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;ProjectAccessError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;success&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="na"&gt;error&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;message&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="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Project FS error:&lt;/span&gt;&lt;span class="dl"&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;success&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="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Internal error.&lt;/span&gt;&lt;span class="dl"&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Request cap check error:&lt;/span&gt;&lt;span class="dl"&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;success&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="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to check model usage limit&lt;/span&gt;&lt;span class="dl"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt; — the same two shared helpers, actually reporting to Sentry with the Cloud-Run-safe flush:&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleFsError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Response&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;unknown&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="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;ProjectAccessError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Expected access-control rejection, not a bug — no Sentry report.&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;success&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="na"&gt;error&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;message&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="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Project FS error:&lt;/span&gt;&lt;span class="dl"&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;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;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// Cloud Run can freeze/scale an instance down right after the response is&lt;/span&gt;
  &lt;span class="c1"&gt;// sent, and Sentry delivers events asynchronously in the background —&lt;/span&gt;
  &lt;span class="c1"&gt;// without this flush, errors on a scaled-down instance can silently never&lt;/span&gt;
  &lt;span class="c1"&gt;// reach Sentry at all. 2s cap so a slow network never hangs the response.&lt;/span&gt;
  &lt;span class="k"&gt;await&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;flush&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;catch&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;success&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="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Internal error.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Same reporting + flush pattern as handleFsError, for routes that build&lt;/span&gt;
&lt;span class="c1"&gt;// their own status code / message instead of the generic "Internal error."&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;reportError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;unknown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;logLabel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;logLabel&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;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;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;await&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;flush&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;catch&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;success&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="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;reportError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to check model usage limit&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Request cap check error:&lt;/span&gt;&lt;span class="dl"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the startup visibility fix, in &lt;code&gt;lib/sentry.ts&lt;/code&gt;:&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;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;initSentry&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dsn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SENTRY_DSN&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;dsn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[sentry] disabled — SENTRY_DSN not set&lt;/span&gt;&lt;span class="dl"&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="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;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;dsn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tracesSampleRate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;sendDefaultPii&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="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[sentry] initialized&lt;/span&gt;&lt;span class="dl"&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;Typechecked clean against the project's existing &lt;code&gt;tsconfig.json&lt;/code&gt;. Zero behavior change from the client's point of view — same status codes, same error messages. The only difference: every error the API actually hits now has a chance of reaching Sentry instead of none.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Use of Sentry
&lt;/h2&gt;

&lt;p&gt;The core insight here isn't "add more &lt;code&gt;captureException&lt;/code&gt; calls" — it's that &lt;strong&gt;Sentry's async delivery model and Cloud Run's freeze-after-response model are directly in tension&lt;/strong&gt;, and the fix has to account for both at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flush before you finish&lt;/strong&gt; — &lt;code&gt;await Sentry.flush(2000)&lt;/code&gt; in a &lt;code&gt;finally&lt;/code&gt; block, capped at 2 seconds so a slow network never hangs a real user's response, is the difference between "Sentry looks configured" and "Sentry actually receives events" on any serverless/scale-to-zero platform.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instrument by construction, not by memory&lt;/strong&gt; — routing every route's error handling through two small shared helpers means the &lt;em&gt;next&lt;/em&gt; route added to this API gets Sentry coverage automatically, instead of depending on someone remembering to add it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make init state visible&lt;/strong&gt; — a one-line startup log turns "is Sentry even working right now?" from a guessing game into something you read off the Cloud Run logs in seconds.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>bugsmash</category>
    </item>
    <item>
      <title>The Missing GitHub Icon That Broke My Production Build</title>
      <dc:creator>Alkhassim Lawal Umar</dc:creator>
      <pubDate>Fri, 24 Jul 2026 19:19:48 +0000</pubDate>
      <link>https://dev.to/alkhassim_lawalumar/the-missing-github-icon-that-broke-my-production-build-b1c</link>
      <guid>https://dev.to/alkhassim_lawalumar/the-missing-github-icon-that-broke-my-production-build-b1c</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/bugsmash"&gt;DEV's Summer Bug Smash: Smash Stories&lt;/a&gt; powered by &lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;I'm building &lt;a href="https://kingxtech.name.ng" rel="noopener noreferrer"&gt;KingxTech&lt;/a&gt;, and specifically &lt;strong&gt;K-XpertAI&lt;/strong&gt; — an AI agent that reads, writes, and deletes files in a live project workspace, then hosts the result instantly. Under the hood it's a React 19 + Vite frontend talking to a TypeScript/Express backend on Cloud Run.&lt;/p&gt;

&lt;p&gt;I'd just shipped a big batch of changes to the workspace UI — a proper code editor, a file tree with GitHub import/export buttons, a terminal tab. Pushed to GitHub, Vercel kicked off the deploy... and it failed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Error: Command "npm run build" exited with 1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Digging into the build log, the real error was buried a few lines down:&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="mi"&gt;15&lt;/span&gt; &lt;span class="err"&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;File&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;FileIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FolderPlus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FilePlus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Trash2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="nx"&gt;RefreshCw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Undo2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Copy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ExternalLink&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Code2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Eye&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Rocket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="nx"&gt;TerminalSquare&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Upload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Maximize2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Minimize2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Github&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FolderInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="nx"&gt;SlidersHorizontal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Plus&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;lucide-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;───┬──&lt;/span&gt;
   &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;╰────&lt;/span&gt; &lt;span class="nx"&gt;Missing&lt;/span&gt; &lt;span class="k"&gt;export&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vite's bundler (via Rolldown) was telling me &lt;code&gt;Github&lt;/code&gt; didn't exist as an export in &lt;code&gt;lucide-react&lt;/code&gt; — but only in Vercel's build. It worked fine in local dev. That's the kind of bug that makes you doubt your own eyes: the icon was clearly imported the same way as a dozen others on that same line that worked perfectly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The investigation
&lt;/h2&gt;

&lt;p&gt;First instinct: check the installed version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"lucide-react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.23.0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing obviously wrong there. So instead of guessing at what icon names &lt;em&gt;should&lt;/em&gt; exist, I installed that exact version in an isolated sandbox and just asked the module directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;icons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lucide-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Github&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FolderInput&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SlidersHorizontal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* ...the rest */&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;icons&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OK&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MISSING&lt;/span&gt;&lt;span class="dl"&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Github MISSING
FolderInput OK
SlidersHorizontal OK
...everything else OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There it was. Every icon in that import worked &lt;em&gt;except&lt;/em&gt; &lt;code&gt;Github&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The root cause
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;lucide-react&lt;/code&gt; — like a lot of modern icon libraries — has been progressively removing brand/trademark logos (GitHub, Twitter, etc.) from its default export set, pushing people toward dedicated brand-icon packages instead. Somewhere between versions, the plain &lt;code&gt;Github&lt;/code&gt; icon quietly stopped being exported. Local dev didn't catch it because of caching in &lt;code&gt;node_modules&lt;/code&gt; from an earlier install; a clean Vercel build (fresh &lt;code&gt;npm install&lt;/code&gt; every time) surfaced it immediately.&lt;/p&gt;

&lt;p&gt;The fix wasn't "install a different package" — it was small enough to just inline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before: relying on a brand icon that no longer ships&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;Github&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;lucide-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// After: a tiny local SVG component instead&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Github&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;14&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 24 24"&lt;/span&gt; &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&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="nt"&gt;path&lt;/span&gt; &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M12 .5C5.7.5.5 5.7.5 12c0 5.1 3.3 9.4 7.9 10.9..."&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="nt"&gt;svg&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;p&gt;Same component name, same usage everywhere else in the file — zero call-site changes needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verifying it, not just eyeballing it
&lt;/h2&gt;

&lt;p&gt;Since the whole failure was "works locally, fails in CI," I didn't trust a visual read of the diff. I ran the actual production build in a clean environment:&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;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;✓ 1902 modules transformed.
dist/index.html                     1.44 kB
dist/assets/index-*.css            24.68 kB
dist/assets/index-*.js           1,185.88 kB
✓ built in 3.16s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean exit code, real &lt;code&gt;dist/&lt;/code&gt; output. Only then did I consider it actually fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm taking away
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A missing export is a build-time contract violation, not a typo&lt;/strong&gt; — treat it like one. Don't guess at what a package &lt;em&gt;should&lt;/em&gt; export; ask it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local dev green ≠ CI green.&lt;/strong&gt; Stale &lt;code&gt;node_modules&lt;/code&gt; can hide exactly this class of bug. A clean install is the only honest test.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brand icons in open-source icon libraries are not guaranteed to stay.&lt;/strong&gt; If your UI depends on a company's logo shape, either pin the package version deliberately or just own a tiny inline SVG — it's one function, and it never breaks on you again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Small bug, but a good reminder that "it built yesterday" is not evidence of anything today.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>bugsmash</category>
    </item>
    <item>
      <title>Building an AI-Native Development Platform: What's New in KingxTech</title>
      <dc:creator>Alkhassim Lawal Umar</dc:creator>
      <pubDate>Sun, 19 Jul 2026 13:21:34 +0000</pubDate>
      <link>https://dev.to/alkhassim_lawalumar/building-an-ai-native-development-platform-whats-new-in-kingxtech-3clo</link>
      <guid>https://dev.to/alkhassim_lawalumar/building-an-ai-native-development-platform-whats-new-in-kingxtech-3clo</guid>
      <description>&lt;h2&gt;
  
  
  Building an AI-Native Development Platform: What's New in KingxTech
&lt;/h2&gt;

&lt;p&gt;How I went from an AI chat interface to an autonomous development workflow.&lt;/p&gt;

&lt;p&gt;Over the past few months, I've been building &lt;strong&gt;KingxTech&lt;/strong&gt;—an AI-native platform for developers. The goal isn't just to add AI to an editor; it's to create a workflow where planning, coding, version control, publishing, and deployment happen in one place.&lt;/p&gt;

&lt;p&gt;This latest update is one of the biggest milestones so far.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🤖 A Better AI Workflow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One thing that always bothered me about AI coding tools is that they often jump straight into editing files.&lt;/p&gt;

&lt;p&gt;I wanted K-XpertAI to work more like a teammate.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Now the workflow looks like this:&lt;/li&gt;
&lt;li&gt;You describe what you want to build.&lt;/li&gt;
&lt;li&gt;K-XpertAI analyzes the request.&lt;/li&gt;
&lt;li&gt;It presents an implementation plan.&lt;/li&gt;
&lt;li&gt;You choose &lt;strong&gt;Accept&lt;/strong&gt; or &lt;strong&gt;Reject&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The AI applies the changes.&lt;/li&gt;
&lt;li&gt;You can Undo any edit if needed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal is to keep developers in control while still benefiting from AI automation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⚡ Live Agent Progress&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of a generic *&lt;em&gt;"Thinking..." *&lt;/em&gt; message, the AI now streams its progress live.&lt;/p&gt;

&lt;p&gt;You'll see updates such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading project files&lt;/li&gt;
&lt;li&gt;Running commands&lt;/li&gt;
&lt;li&gt;Building components&lt;/li&gt;
&lt;li&gt;Editing files&lt;/li&gt;
&lt;li&gt;Cleaning up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Watching the agent work makes the process much easier to follow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧠 Multiple AI Models&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;K-XpertAI now supports choosing different models for different tasks.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;p&gt;`:G-flash/ Explain this code&lt;/p&gt;

&lt;p&gt;:C-sonnet/ Refactor this project&lt;/p&gt;

&lt;p&gt;:O-terra/ Optimize performance`&lt;/p&gt;

&lt;p&gt;For everyday development, there's also a free default model available without consuming monthly credits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📊 Credits That Make Sense&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Free users now receive &lt;strong&gt;300 AI credits every month.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Premium models consume different amounts depending on their capability, while the default free model remains available for basic coding assistance.&lt;/p&gt;

&lt;p&gt;The Console also includes a complete usage history so developers can track how their credits are being used.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🚀 GitHub Integration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of my favorite additions is GitHub integration.&lt;/p&gt;

&lt;p&gt;The workflow is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate a Personal Access Token.&lt;/li&gt;
&lt;li&gt;Connect it to your KingxTech account.&lt;/li&gt;
&lt;li&gt;Push your project directly from the workspace
.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No switching between multiple applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🌐 One-Click Publishing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Projects can now be published directly from the workspace.&lt;/p&gt;

&lt;p&gt;Instead of sharing a long project ID, each published project receives a cleaner permanent URL.&lt;/p&gt;

&lt;p&gt;Custom domain support is also built into the workflow by generating the required DNS records.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💻 Built-in Terminal&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A new Terminal tab lets developers run safe commands directly inside the workspace.&lt;/p&gt;

&lt;p&gt;This keeps common development tasks close to the editor instead of requiring another terminal window.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📈 Why I'm Building This&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My goal isn't to create another AI chatbot.&lt;/p&gt;

&lt;p&gt;I'm trying to build a developer platform where AI naturally fits into the software development lifecycle.&lt;/p&gt;

&lt;p&gt;That includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;AI assistance&lt;/li&gt;
&lt;li&gt;Project workspaces&lt;/li&gt;
&lt;li&gt;Version control&lt;/li&gt;
&lt;li&gt;Publishing&lt;/li&gt;
&lt;li&gt;Domains&lt;/li&gt;
&lt;li&gt;Cloud infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...working together as one experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's Next&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I'm currently working on:&lt;/li&gt;
&lt;li&gt;Better multi-model routing&lt;/li&gt;
&lt;li&gt;Richer project previews&lt;/li&gt;
&lt;li&gt;Improved AI planning&lt;/li&gt;
&lt;li&gt;Cloud integration&lt;/li&gt;
&lt;li&gt;More developer tooling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's still a lot to build, but this update feels like a major step toward the platform I originally imagined.&lt;/p&gt;

&lt;p&gt;If you're interested in AI-assisted software development, I'd love to hear your thoughts and feedback.&lt;/p&gt;

&lt;p&gt;Website: &lt;a href="https://kingxtech.name.ng" rel="noopener noreferrer"&gt;https://kingxtech.name.ng&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/KingzTechCompy" rel="noopener noreferrer"&gt;https://github.com/KingzTechCompy&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>showdev</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Building K-xpertAI: A Developer Assistant Powered by KX-NeuroCore &amp; Gemma 4</title>
      <dc:creator>Alkhassim Lawal Umar</dc:creator>
      <pubDate>Sat, 16 May 2026 23:20:02 +0000</pubDate>
      <link>https://dev.to/alkhassim_lawalumar/building-k-xpertai-a-developer-assistant-powered-by-kx-neurocore-gemma-4-2hj8</link>
      <guid>https://dev.to/alkhassim_lawalumar/building-k-xpertai-a-developer-assistant-powered-by-kx-neurocore-gemma-4-2hj8</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpe1h9o19ymuhso1sx08s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpe1h9o19ymuhso1sx08s.png" alt=" " width="720" height="1520"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2oj78jhckoccbp27lpb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2oj78jhckoccbp27lpb.png" alt=" " width="720" height="1520"&gt;&lt;/a&gt;## Introduction&lt;br&gt;
At &lt;strong&gt;KingxTech&lt;/strong&gt;, the goal is to build a complete AI ecosystem for developers — tools that help programmers debug, build, and plan projects more efficiently.&lt;/p&gt;

&lt;p&gt;The first major step in that vision is &lt;strong&gt;K-xpertAI&lt;/strong&gt;, a developer-focused AI assistant designed for coding support, deployment troubleshooting, and architecture planning.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Model
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Google Gemma 4 (26B)&lt;/strong&gt;&lt;br&gt;
Chosen for its advanced reasoning, extensive coding knowledge, and low-latency technical responses. The 26B parameter model provides the perfect balance between high-level logic and processing speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Engine: KX-NeuroCore (Logic Layer)
&lt;/h3&gt;

&lt;p&gt;The custom logic layer responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Context Optimization:&lt;/strong&gt; Managing memory efficiency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response Control:&lt;/strong&gt; Shaping raw AI output into developer-ready advice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart Processing:&lt;/strong&gt; Handling complex request routing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Backend: Netlify Serverless
&lt;/h3&gt;

&lt;p&gt;Powered by &lt;strong&gt;Node.js&lt;/strong&gt; and &lt;strong&gt;Netlify Functions&lt;/strong&gt;. Using a serverless architecture allowed for rapid deployment and automatic scaling without the overhead of traditional server management.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend: NeuroCore UI
&lt;/h3&gt;

&lt;p&gt;A custom HTML/CSS interface focused on a futuristic, high-contrast aesthetic. It features a terminal-inspired layout, JetBrains Mono typography, and high-performance rendering to match a developer's fast-paced workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge: The “Scrubber” System
&lt;/h2&gt;

&lt;p&gt;One of the primary challenges during development was optimizing the model’s raw &lt;strong&gt;Chain of Thought (CoT)&lt;/strong&gt; output for a production UI.&lt;br&gt;
Gemma 4 is highly analytical, often outputting its internal planning and validation steps. While useful for the AI, this "noise" can clutter a clean user interface. To solve this, I built a custom &lt;strong&gt;Scrubber System&lt;/strong&gt; that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Regex Filtering:&lt;/strong&gt; Strips internal metadata headers and self-evaluation checklists.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Noise Reduction:&lt;/strong&gt; Removes unnecessary reasoning fragments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Formatting Preservation:&lt;/strong&gt; Ensures that code blocks and technical explanations remain intact while removing the "meta" chatter.
This makes K-xpertAI feel faster, cleaner, and more like a production-ready engineering tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Performance Optimization
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Context Windowing
&lt;/h3&gt;

&lt;p&gt;To maintain high response speeds and token efficiency, I implemented &lt;strong&gt;Context Slicing&lt;/strong&gt; (history.slice(-4)). This ensures the model stays hyper-focused on the current technical task while maintaining enough memory to understand the conversation flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Temperature Tuning
&lt;/h3&gt;

&lt;p&gt;I tuned the model temperature to &lt;strong&gt;0.7&lt;/strong&gt;. Through testing, this proved to be the "sweet spot" for developers — high enough to provide creative architectural solutions, but low enough to maintain strict technical accuracy for debugging and code generation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;p&gt;K-xpertAI is built for practical engineering workflows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deployment Debugging:&lt;/strong&gt; Specialized logic for resolving Netlify 500 errors and environment configuration issues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Full-Stack Assistance:&lt;/strong&gt; Expert-level help with JavaScript, Node.js, and modern framework architecture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;System Design:&lt;/strong&gt; Planning scalable backend structures and API integrations.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;K-xpertAI is the foundation of the larger &lt;strong&gt;KingxTech AI ecosystem&lt;/strong&gt;. By combining the power of &lt;strong&gt;Gemma 4&lt;/strong&gt;, the scalability of &lt;strong&gt;Netlify&lt;/strong&gt;, and the custom optimization of &lt;strong&gt;KX-NeuroCore&lt;/strong&gt;, we've created a tool that bridges the gap between raw AI potential and real-world engineering needs.&lt;/p&gt;

&lt;p&gt;This is just the beginning of the KingxTech journey.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live Demo:&lt;/strong&gt; &lt;a href="https://kxpertai.netlify.app/" rel="noopener noreferrer"&gt;https://kxpertai.netlify.app/&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository:&lt;/strong&gt;. &lt;a href="https://github.com/KingzAlkhasim/K-Xpert" rel="noopener noreferrer"&gt;https://github.com/KingzAlkhasim/K-Xpert&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gemmachallenge</category>
      <category>gemma</category>
      <category>kingxtech</category>
      <category>ai</category>
    </item>
    <item>
      <title>How to Fine-Tune a Llama Model on Hugging Face Using Python</title>
      <dc:creator>Alkhassim Lawal Umar</dc:creator>
      <pubDate>Fri, 08 May 2026 22:30:59 +0000</pubDate>
      <link>https://dev.to/alkhassim_lawalumar/how-to-fine-tune-a-llama-model-on-hugging-face-using-python-2gic</link>
      <guid>https://dev.to/alkhassim_lawalumar/how-to-fine-tune-a-llama-model-on-hugging-face-using-python-2gic</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction: Why Is This Topic Important?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Large Language Models (LLMs) like &lt;strong&gt;Llama by Meta AI&lt;/strong&gt; have changed the way developers build AI applications. Instead of creating models from scratch, developers can now fine-tune existing models for specific tasks such as chatbots, coding assistants, summarization tools, or customer support systems.&lt;br&gt;
&lt;strong&gt;Fine-tuning&lt;/strong&gt; is important because a pre-trained model already understands language patterns, but it may not understand your specific use case. By training the model on your own dataset, you can make it respond in a more accurate and specialized way.&lt;br&gt;
Thanks to &lt;strong&gt;Hugging Face&lt;/strong&gt; and Python libraries like Transformers, the process has become much easier than it used to be. With only a few lines of code, developers can load a Llama model, prepare a dataset, and start training.&lt;br&gt;
In this article, we will walk through the full process step by step in a simple and practical way.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;The Setup: Installing the Required Libraries&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before we start training the model, we need to install the required Python libraries. Open your terminal or command prompt and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;transformers datasets accelerate peft trl torch

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Here is what each library does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;transformers&lt;/strong&gt;: Used for loading and working with Llama models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;datasets&lt;/strong&gt;: Helps us load and manage training datasets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;accelerate&lt;/strong&gt;: Makes training faster and easier on GPUs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;peft&lt;/strong&gt;: Allows parameter-efficient fine-tuning techniques like &lt;em&gt;LoRA&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;trl&lt;/strong&gt;: Provides training utilities for language models (Post-Training).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;torch&lt;/strong&gt;: The main deep learning framework used by Hugging Face.
### &lt;strong&gt;The Core: Fine-Tuning Step by Step&lt;/strong&gt;
#### &lt;strong&gt;Step 1: Import the Required Modules&lt;/strong&gt;
The first thing we do is import the libraries we need into our Python script.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AutoTokenizer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AutoModelForCausalLM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TrainingArguments&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datasets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dataset&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;trl&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SFTTrainer&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AutoTokenizer&lt;/strong&gt;: Converts text into tokens that the model understands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AutoModelForCausalLM&lt;/strong&gt;: Loads the Llama language model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TrainingArguments&lt;/strong&gt;: Stores your specific training settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;load_dataset&lt;/strong&gt;: Pulls datasets directly from the Hugging Face Hub.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SFTTrainer&lt;/strong&gt;: Handles the heavy lifting of Supervised Fine-Tuning.
#### &lt;strong&gt;Step 2: Load the Llama Model&lt;/strong&gt;
Now we load the tokenizer and the model weights.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;model_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta-llama/Llama-3-8B&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;tokenizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AutoTokenizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AutoModelForCausalLM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Note:&lt;/em&gt; You need access permission for Meta's Llama models on Hugging Face before downloading them. Ensure you are logged in using huggingface-cli login.
#### &lt;strong&gt;Step 3: Load a Dataset&lt;/strong&gt;
Next, we load a dataset for training. For this example, we’ll use a subset of movie reviews.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;dataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;load_dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;imdb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;train[:1000]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;split="train[:1000]"&lt;/strong&gt; loads only the first 1000 examples. Smaller datasets are useful for testing your code before committing to a full training run.
#### &lt;strong&gt;Step 4: Configure the Tokenizer&lt;/strong&gt;
Some Llama models require a padding token to handle batches of text.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pad_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eos_token&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why is this necessary?&lt;/strong&gt; Models process text in batches. Short sentences need "padding" so all inputs have the same length. We use the &lt;em&gt;end-of-sequence (EOS)&lt;/em&gt; token to fill that space.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 5: Set Training Arguments&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Now we define the configuration for our training "engine."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;training_args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TrainingArguments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;output_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./llama-finetuned&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;per_device_train_batch_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;num_train_epochs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;logging_steps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;save_steps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;output_dir&lt;/strong&gt;: The folder where your results will live.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;per_device_train_batch_size&lt;/strong&gt;: Set to 2 to avoid running out of GPU memory (VRAM).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;num_train_epochs&lt;/strong&gt;: How many times the model sees the entire dataset.
#### &lt;strong&gt;Step 6: Create the Trainer&lt;/strong&gt;
We connect the model, the data, and the settings together.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;trainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SFTTrainer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;train_dataset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;training_args&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of manually writing a complex training loop, the &lt;strong&gt;SFTTrainer&lt;/strong&gt; automates backpropagation and weight updates for us.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 7: Start Fine-Tuning&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This is the moment of truth. Run the following command to start the engine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;trainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;train&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During this stage, the model reads the text, predicts the next word, calculates the error, and &lt;strong&gt;updates itself&lt;/strong&gt; to become more accurate for your specific data.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 8: Save Your Work&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Once training is complete, save the fine-tuned weights so you can use them in your apps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;trainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./final-llama-model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;The Conclusion: What Did We Learn?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In this article, we covered the essential workflow for adapting a state-of-the-art model to your needs. We learned how to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prepare the environment&lt;/strong&gt; with specialized AI libraries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load gated models&lt;/strong&gt; from Meta and Hugging Face.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure training parameters&lt;/strong&gt; like batch size and epochs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Save and export&lt;/strong&gt; a specialized model.
&lt;strong&gt;What's Next?&lt;/strong&gt;
As you continue your journey, I recommend exploring &lt;strong&gt;LoRA (Low-Rank Adaptation)&lt;/strong&gt; and &lt;strong&gt;Quantization&lt;/strong&gt;. These techniques allow you to fine-tune massive models on much cheaper hardware, which is a game-changer for independent developers and startups.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;About the Author:&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;I am a Full-Stack Developer and UI/UX Designer dedicated to building the next generation of tech tools. Through KingxTech, I develop everything from professional IDEs to custom AI models like KX-NeuroCore. My focus is on technical clarity and performance, ensuring that the intersection of web development and AI is powerful, efficient, and open to all.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
