shadcn-ui/ui · error

We could not find a valid `ui` path in your `components.json

Error message

We could not find a valid `ui` path in your `components.json` file. Please ensure you have a valid `ui` path in your `components.json` file.

What it means

Thrown by migrateRadix when no --path was given and config.resolvedPaths.ui is falsy. The default behavior is to scan the configured `ui` directory; without it the migrator has no fallback. The message instructs the user to fix components.json.

Source

Thrown at packages/shadcn/src/migrations/migrate-radix.ts:148

        files = await fg("**/*.{js,ts,jsx,tsx}", {
          cwd: basePath,
          onlyFiles: true,
          ignore: ["**/node_modules/**"],
        })
      } else if (stat.isFile()) {
        files = [options.path]
      } else {
        throw new Error(`Unsupported path type: ${options.path}`)
      }
    }

    if (files.length === 0) {
      throw new Error(`No files found matching: ${options.path}`)
    }
  } else {
    // Default: use ui path from components.json.
    if (!config.resolvedPaths.ui) {
      throw new Error(
        "We could not find a valid `ui` path in your `components.json` file. Please ensure you have a valid `ui` path in your `components.json` file."
      )
    }

    basePath = config.resolvedPaths.ui
    files = await fg("**/*.{js,ts,jsx,tsx}", {
      cwd: basePath,
      onlyFiles: true,
    })
  }

  // Confirm with user.
  if (!options.yes) {
    const relativePath = options.path
      ? options.path
      : `./${path.relative(config.resolvedPaths.cwd, basePath)}`

    const { confirm } = await prompts({

View on GitHub (pinned to efac598707)

Solutions

  1. Add `aliases.ui` to components.json (e.g. "@/components/ui").
  2. Re-run `npx shadcn@latest init`.
  3. Pass `--path` to bypass the ui-path fallback.
  4. Programmatic callers: resolve Config via get-config before calling migrateRadix.

Example fix

// before — components.json without aliases.ui
"aliases": { "components": "@/components" }

// after
"aliases": { "components": "@/components", "ui": "@/components/ui" }
Defensive patterns

Strategy: validation

Validate before calling

function assertUiPathForRadix(config: Config) {
  if (!config.resolvedPaths.ui) {
    throw new Error('Run `npx shadcn@latest init` to set aliases.ui, or pass --path.')
  }
}

if (!options.path) assertUiPathForRadix(config)

Type guard

function hasUiPath(c: Partial<Config>): c is Config & { resolvedPaths: { ui: string } } {
  return Boolean(c.resolvedPaths?.ui)
}

Try / catch

try {
  await migrateRadix(config)
} catch (e) {
  if (e instanceof Error && e.message.includes('valid `ui` path')) {
    await migrateRadix(config, { path: './src/components/ui' })
  } else throw e
}

Prevention

When it happens

Trigger: Running `shadcn migrate radix` (no --path) on a project whose components.json lacks `aliases.ui`; programmatic call to migrateRadix with a Config missing resolvedPaths.ui.

Common situations: Hand-edited components.json with the `ui` alias removed; project never ran `shadcn init`; partial Config built programmatically without resolving aliases.

Related errors


AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12). Data as JSON: /api/errors/bbaa895dcc00bc9d. Report an issue: GitHub.