shadcn-ui/ui · error · Error
Unknown base color: ${sourceBaseColor}.
Error message
Unknown base color: ${sourceBaseColor}. What it means
migrateBaseColor fetches the source palette definition via getRegistryBaseColor(sourceBaseColor), which loads colors/<name>.json from the registry. The source is intentionally NOT validated against BASE_COLORS earlier (legacy colors like slate are allowed), so an unrecognized name surfaces here as "Unknown base color" when the lookup resolves without a usable color. (A hard 404 on the registry instead raises a separate registry fetch error.)
Source
Thrown at packages/shadcn/src/migrations/migrate-base-color.ts:137
initial: true,
message: `We will migrate ${highlighter.info(
relativePath
)} from ${highlighter.info(sourceBaseColor)} to ${highlighter.info(
targetBaseColor
)}. Continue?`,
})
if (!confirm) {
logger.info("Migration cancelled.")
process.exit(0)
}
}
const sourceColor = await getRegistryBaseColor(sourceBaseColor)
const targetColor = await getRegistryBaseColor(targetBaseColor)
if (!sourceColor) {
throw new Error(`Unknown base color: ${sourceBaseColor}.`)
}
if (!targetColor) {
throw new Error("Something went wrong fetching the base colors.")
}
const projectInfo = await getProjectInfo(config.resolvedPaths.cwd)
const tailwindVersion = projectInfo?.tailwindVersion ?? "v4"
const sourceVars = getBaseColorCssVars(sourceColor, tailwindVersion)
const targetVars = getBaseColorCssVars(targetColor, tailwindVersion)
const migrationSpinner = spinner(`Migrating base color...`)?.start()
const raw = await fs.readFile(config.resolvedPaths.tailwindCss, "utf-8")
const { cssVars, skipped } = getBaseColorMigration(
raw,
sourceVars,View on GitHub (pinned to c06da1d0e9)
Solutions
- Pass an explicit, existing source: `--from neutral` (or another available name) instead of relying on the config value.
- Fix components.json: set tailwind.baseColor to a supported name (neutral, zinc, stone, mauve, olive, mist, taupe) and re-run.
- If REGISTRY_URL points at a private mirror, verify it actually serves colors/<name>.json (curl $REGISTRY_URL/colors/neutral.json); otherwise unset the override so the default registry is used.
Example fix
// before — components.json has a stale/custom name
"tailwind": { "baseColor": "slate-dark", ... }
npx shadcn@latest migrate base-color --to neutral
// -> Unknown base color: slate-dark.
// after
"tailwind": { "baseColor": "neutral", ... }
npx shadcn@latest migrate base-color --to zinc Defensive patterns
Strategy: try-catch
Validate before calling
const AVAILABLE = new Set(['neutral', 'zinc', 'stone', 'mauve', 'olive', 'mist', 'taupe', /* legacy sources your registry still serves, e.g. */ 'slate', 'gray'])
// Validate --from (or the config's baseColor) before running the CLI:
function assertKnownSource(name: string | undefined): void {
if (!name || !AVAILABLE.has(name)) {
throw new Error(
`Unknown source base color "${name}". Fix tailwind.baseColor in components.json or pass --from.`
)
}
} Type guard
function isKnownBaseColor(name: string): boolean {
const available = ['neutral', 'zinc', 'stone', 'mauve', 'olive', 'mist', 'taupe', 'slate', 'gray']
return available.includes(name)
} Try / catch
try {
await migrateBaseColor(config, { from, to, yes: true })
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
if (message.startsWith('Unknown base color:')) {
// Input problem: fix --from or tailwind.baseColor in components.json, then retry.
const bad = message.match(/Unknown base color: (\w+)/)?.[1]
throw new Error(`Fix the base color "${bad}" in components.json or pass --from with a valid name.`)
}
throw error // registry/network errors bubble up separately
} Prevention
- Keep tailwind.baseColor in components.json set to a name your registry actually serves (check colors/<name>.json).
- Pin REGISTRY_URL mirrors that replicate the full colors/*.json set, or unset the override.
- In CI, pre-flight the source palette: `curl -sf $REGISTRY_URL/colors/$FROM.json > /dev/null` before invoking the migration.
When it happens
Trigger: Passing --from with a name the registry does not serve (custom typo, invented name), or having a stale/custom `tailwind.baseColor` in components.json that no colors/<name>.json exists for — especially when REGISTRY_URL points at a private mirror that omits the legacy color files.
Common situations: Old projects carrying legacy palette names in components.json; corporate registries/mirrors that only proxy component items but not colors/*.json; hand-edited configs; a REGISTRY_URL override left set in the environment.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Something went wrong fetching the base colors.
- No ${highlighter.info("components.json")} or ${highlighter.i
- Failed to read config at ${options.cwd}.
- Something went wrong fetching the registry icons.
- INVALID_CONFIG
AI-assisted analysis of shadcn-ui/ui@c06da1d0e9 (2026-08-21).
Data as JSON: /api/errors/b7cc8dd03feb7ad5.
Report an issue: GitHub.