shadcn-ui/ui · error · Error
The cn migration requires Tailwind CSS v4 and tailwind-merge
Error message
The cn migration requires Tailwind CSS v4 and tailwind-merge v3. Tailwind CSS v3 projects should continue using tailwind-merge v2.
What it means
The cn migration rewrites cn() helpers built on tailwind-merge v3 semantics, which only work with Tailwind CSS v4. assertTailwindCompatibility reads tailwindcss and tailwind-merge versions from package.json (dependencies/devDependencies/optional/peer) and throws if the declared major of either is below the required minimum (v4 and v3 respectively; workspace/protocol specifiers are treated as satisfying).
Source
Thrown at packages/shadcn/src/migrations/cn/index.ts:144
cwd: string,
migratedPackages: Set<OldPackage>
) {
if (!migratedPackages.has("tailwind-merge")) {
return
}
const packageInfo = getPackageInfo(cwd, false)
const tailwindVersion = findDependencyVersion(packageInfo, "tailwindcss")
const tailwindMergeVersion = findDependencyVersion(
packageInfo,
"tailwind-merge"
)
if (
(getDeclaredMajor(tailwindVersion) ?? 4) < 4 ||
(getDeclaredMajor(tailwindMergeVersion) ?? 3) < 3
) {
throw new Error(
"The cn migration requires Tailwind CSS v4 and tailwind-merge v3. Tailwind CSS v3 projects should continue using tailwind-merge v2."
)
}
}
function findDependencyVersion(
packageInfo: ReturnType<typeof getPackageInfo>,
packageName: string
) {
return (
packageInfo?.dependencies?.[packageName] ??
packageInfo?.devDependencies?.[packageName] ??
packageInfo?.optionalDependencies?.[packageName] ??
packageInfo?.peerDependencies?.[packageName]
)
}
function getDeclaredMajor(version?: string) {View on GitHub (pinned to 5c7072da67)
Solutions
- Upgrade to Tailwind CSS v4 (`npx @tailwindcss/upgrade`) before running the cn migration.
- Upgrade tailwind-merge to v3: `npm install tailwind-merge@^3`.
- If you must stay on Tailwind v3, keep tailwind-merge v2 and do not run the cn migration for that project.
- Check package.json for stale pins/resolutions (e.g. overrides forcing tailwind-merge@2) and remove them.
Example fix
// before (package.json) "tailwindcss": "^3.4.0", "tailwind-merge": "^2.2.0" // after "tailwindcss": "^4.0.0", "tailwind-merge": "^3.0.0"
Defensive patterns
Strategy: validation
Validate before calling
import { readFileSync } from 'fs'
const pkg = JSON.parse(readFileSync('package.json', 'utf8'))
const deps = { ...pkg.dependencies, ...pkg.devDependencies }
if (parseInt(deps['tailwindcss']?.match(/\d+/)?.[0] ?? '4', 10) < 4 ||
parseInt(deps['tailwind-merge']?.match(/\d+/)?.[0] ?? '3', 10) < 3) {
throw new Error('Upgrade to tailwindcss@4 and tailwind-merge@3 before migrating')
} Prevention
- Migrate Tailwind v3 -> v4 with the official upgrade tool before running the cn migration.
- Keep tailwind-merge on v3 across all monorepo workspaces.
- Remove package overrides/resolutions that pin tailwind-merge to v2.
When it happens
Trigger: migrateCn detecting tailwind-merge usage in migrated files while package.json declares tailwindcss 3.x or tailwind-merge 2.x (or neither is declared at a valid semver major).
Common situations: Upgrading a Tailwind v3 project to the new cn utility without first migrating Tailwind itself; a monorepo app that still pins tailwind-merge@^2 while others use v3; the packages missing from package.json entirely so majors fall back to 4/3 — the throw only fires on a declared lower major.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Could not resolve shadcn/tailwind.css.
- NOT_CONFIGURED
- Invalid input: not an object literal
- We could not find a valid CSS file in your `components.json`
- The `base-color` migration requires CSS variables. Your `com
AI-assisted analysis of shadcn-ui/ui@5c7072da67 (2026-09-07).
Data as JSON: /api/errors/befb52891d984e33.
Report an issue: GitHub.