🚀 Executive Summary
TL;DR: shadcn/ui builds recently broke due to a silent dependency update in `@radix-ui/react-primitive` (version 1.0.3+) which introduced a new dependency on `@mui/base`, causing conflicts, especially in projects already using Material UI. The primary solutions involve either pinning `@radix-ui/react-primitive` to version `1.0.2` using package manager overrides, performing a proper dependency upgrade to align all MUI and shadcn/ui packages, or a complete `node_modules` and cache clear followed by a fresh install.
🎯 Key Takeaways
- A silent dependency update in `@radix-ui/react-primitive` (specifically version 1.0.3 and above) introduced a new dependency on `@mui/base`, causing build failures in shadcn/ui projects.
- The issue manifests as `FATAL ERROR: Type ‘unstable_ClassNameGenerator’ is not assignable…` due to version conflicts when `@mui/base` is pulled in unexpectedly.
- Immediate fixes include using package manager `overrides` to pin `@radix-ui/react-primitive` to `1.0.2`, while long-term solutions involve analyzing and properly upgrading conflicting `@mui` and shadcn/ui packages, or a full `node_modules` and cache reset.
Your shadcn/ui build just broke with weird Base UI errors, and you’re scrambling for a fix? You’re not alone. A silent dependency update is the likely culprit, and here are three ways to fix your pipeline, from a quick patch to a permanent solution.
Did shadcn/ui Just Break Your Build? A Deep Dive into the Silent Base UI Dependency
It was 3 AM on a Tuesday. The on-call phone buzzed, waking me from a dream about finally automating my coffee machine. The alert was cryptic: FATAL ERROR: Type 'unstable_ClassNameGenerator' is not assignable.... The pipeline for our main customer dashboard, which hadn’t been touched in weeks, was glowing red on ci-runner-04. My first thought? DNS. It’s always DNS. Except this time, it wasn’t. This was something much more subtle and, frankly, much more annoying: dependency hell, served fresh by a silent update.
The “Why”: What Actually Happened?
After a frantic hour of digging through build logs and dependency trees, we traced it back. It wasn’t our code. A core dependency of shadcn/ui, specifically @radix-ui/react-primitive, had quietly pushed a new version. This new version introduced a dependency on @mui/base (Material UI’s Base UI). If you, like many teams, were already using a different version of MUI or had a strict dependency tree in your monorepo, everything just exploded.
There was no big announcement, no major version bump signifying a breaking change. Just a minor patch that cascaded into a complete build failure. This is a classic case of dependency drift, where the ground shifts beneath your feet without you changing a single line of your own code. It’s frustrating, but it’s a reality of modern development.
The Fixes: From a Band-Aid to a Cure
Okay, enough context. You’re here because your build is broken and your manager is asking for an ETA. Let’s get you back online. I’ve got three approaches, from the immediate “stop the bleeding” fix to the proper long-term solution.
Solution 1: The ‘Get Me Back to Sleep’ Override
This is the fastest way to get your pipeline green again. We’re going to tell our package manager to ignore the problematic new version of the Radix component and use a known good, older version. It’s a hack, but it’s an effective one.
You do this by adding an "overrides" (for npm/yarn) or "pnpm": {"overrides": ...} (for pnpm) block to your root package.json file. You want to pin @radix-ui/react-primitive to version 1.0.2, which is the last version before the @mui/base dependency was added.
For PNPM users:
{
"pnpm": {
"overrides": {
"@radix-ui/react-primitive": "1.0.2"
}
}
}
For NPM/Yarn users:
{
"overrides": {
"@radix-ui/react-primitive": "1.0.2"
}
}
After adding this, delete your lock file (pnpm-lock.yaml, package-lock.json) and your node_modules directory, then run install again. Your build should now pass.
Warning: This is a temporary patch. Overrides can mask other underlying issues and can become technical debt. Use this to get stable, then plan to implement Solution 2.
Solution 2: The ‘Let’s Do This Properly’ Upgrade
The root cause is a version mismatch. The right way to fix this is to bring your dependencies into alignment. This means you might need to update your other Material UI packages or even shadcn/ui itself to versions that are compatible with this new dependency structure.
- Analyze the Conflict: Run
npm ls @mui/baseor the equivalent for your package manager to see which packages are pulling in which versions. This will tell you exactly where the conflict is. - Update Your Packages: You’ll likely need to update your primary
@mui/materialpackage to a newer version that plays nicely. - Run shadcn/ui diff: If you’re using the shadcn/ui CLI, run the
diffcommand to see if any of your components are out of date with the latest version, which may have already accounted for this change. - Test Thoroughly: This is not a blind update. A dependency upgrade requires regression testing. Check your UI for any visual or functional breakages. This takes more time, but it’s the only way to be sure you’ve actually solved the problem instead of just hiding it.
Solution 3: The ‘Nuke and Pave’ Approach
Sometimes, the issue isn’t just the dependency versions in your package.json; it’s a corrupted cache or a stubborn lock file that refuses to resolve correctly. When you’re absolutely sure your versions are correct but things are still failing, it’s time to burn it all down.
This is more than just deleting node_modules. It’s a full-on cleansing:
# 1. Nuke the node_modules directory
rm -rf node_modules
# 2. Nuke the lock file
rm -f package-lock.json pnpm-lock.yaml yarn.lock
# 3. Clear your package manager's cache
npm cache clean --force
# or pnpm store prune
# 4. Reinstall everything from scratch
npm install
Pro Tip: This is a sledgehammer for a thumbtack, but in my years of experience, it solves a surprising 30% of “weird” front-end build issues that defy logical explanation. It’s the “have you tried turning it off and on again?” of the Node.js world.
Comparing the Solutions
Here’s a quick breakdown to help you decide which path to take:
| Solution | Effort | Risk | Best For |
|---|---|---|---|
| 1. The Override | Low | Medium (Tech Debt) | Emergency hotfixes; getting the build green immediately. |
| 2. The Proper Upgrade | High | Low (If tested) | The correct long-term solution for a healthy codebase. |
| 3. The Nuke & Pave | Medium | Low | When you suspect a corrupted cache or inconsistent lock file. |
Ultimately, this incident is a great reminder that our applications are built on layers of dependencies, and any one of them can change without warning. Locking your versions, using tools like Dependabot carefully, and having a solid rollback plan are your best defenses. Now, go get that pipeline green.
🤖 Frequently Asked Questions
âť“ Why did my shadcn/ui build suddenly break with Base UI errors?
Your shadcn/ui build likely broke due to a silent dependency update in `@radix-ui/react-primitive` (version 1.0.3 or higher), which introduced a new dependency on `@mui/base`. This can cause conflicts if your project already uses a different version of Material UI or has a strict dependency tree.
âť“ How do the different solutions for the shadcn/ui Base UI conflict compare?
The ‘Override’ solution (pinning `@radix-ui/react-primitive` to `1.0.2`) is a low-effort, medium-risk emergency fix. The ‘Proper Upgrade’ involves high effort but low risk (if tested), aligning all dependencies for a healthy codebase. The ‘Nuke & Pave’ approach (clearing cache and reinstalling) is medium effort, low risk, and best for resolving corrupted caches or stubborn lock file issues.
âť“ What is a common implementation pitfall when using dependency overrides to fix this issue?
A common pitfall with using `overrides` is that they can mask other underlying dependency issues and accumulate technical debt. While effective for immediate fixes, it’s crucial to treat them as temporary patches and plan for a proper dependency alignment or upgrade.
Leave a Reply