Back

Vite: Fix "Failed to resolve import" (path aliases)

Vite: Fix "Failed to resolve import" (path aliases)

You’ve just set up path aliases in your Vite project, replacing those unwieldy ../../../components imports with clean @/components paths. But now Vite throws a frustrating error: “Failed to resolve import”. This happens because Vite and TypeScript handle module resolution differently, and fixing it requires syncing two separate configurations.

This guide shows you exactly how to fix Vite path aliases errors using two proven methods: manual configuration for full control, or the automated vite-tsconfig-paths plugin for simplicity.

Key Takeaways

  • Vite and TypeScript require separate path alias configurations that must align
  • Manual configuration offers full control but requires maintaining two config files
  • The vite-tsconfig-paths plugin automates synchronization between configs
  • Common issues include missing @types/node, syntax mismatches, and ESM conflicts

The “Failed to resolve import” Error in Vite

The Vite Failed to resolve import error appears when your bundler can’t locate modules using your custom path aliases. You’ll see variations like:

  • [vite] Internal server error: Failed to resolve import "@/components/Header"
  • Cannot find module '@/utils' or its corresponding type declarations
  • TypeScript error TS2307 in your IDE

These errors block your development server, break hot module replacement, and prevent successful builds—turning what should be a productivity boost into a roadblock.

Understanding Why Vite Path Aliases Fail

The Two-Config Problem

Vite uses Rollup for bundling, while TypeScript handles type checking separately. Each tool needs its own configuration:

  • Vite needs resolve.alias in vite.config.ts for module bundling
  • TypeScript needs paths in tsconfig.json for type checking and IDE support

When these configurations don’t match, you get import resolution errors. Vite might understand @/components, but TypeScript doesn’t—or vice versa.

Common Triggers for Import Errors

Three issues cause most Vite resolve alias errors:

  1. Missing Node.js types: Using path.resolve() without @types/node
  2. Syntax mismatches: Vite uses object notation while TypeScript uses array patterns
  3. Module format conflicts: Using CommonJS-specific variables like __dirname in ESM projects

Method 1: Manual Configuration for Vite TypeScript Aliases

Step 1: Configure vite.config.ts

First, install the required Node.js types:

npm install -D @types/node

Then update your Vite configuration:

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { fileURLToPath, URL } from 'node:url'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
      '@components': fileURLToPath(new URL('./src/components', import.meta.url)),
      '@utils': fileURLToPath(new URL('./src/utils', import.meta.url))
    }
  }
})

For CommonJS projects, you can use path.resolve() with __dirname:

// vite.config.ts (CommonJS)
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@components': path.resolve(__dirname, './src/components'),
      '@utils': path.resolve(__dirname, './src/utils')
    }
  }
})

Step 2: Update tsconfig.json

Configure TypeScript to recognize the same aliases:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@utils/*": ["src/utils/*"]
    }
  }
}

Note the syntax difference: Vite uses '@components' while TypeScript uses "@components/*" with array values.

Verifying Your Setup

Test your configuration with an import:

// Before: import Button from '../../../components/Button'
import Button from '@components/Button'

Your IDE should provide autocomplete suggestions, and npm run dev should start without errors.

Method 2: Automated Setup with vite-tsconfig-paths

Installation and Basic Setup

The vite-tsconfig-paths plugin automatically syncs your TypeScript paths with Vite:

npm install -D vite-tsconfig-paths

Update your Vite config:

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tsconfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
  plugins: [react(), tsconfigPaths()]
})

That’s it. The plugin reads your tsconfig.json paths and configures Vite automatically.

Benefits Over Manual Configuration

  • Single source of truth: Update only tsconfig.json
  • No synchronization errors: Aliases always match
  • Cleaner config files: Less boilerplate code
  • Monorepo support: Handles complex workspace setups

Troubleshooting Vite Resolve Alias Errors

JavaScript Projects Without TypeScript

For JavaScript projects, create a jsconfig.json instead:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

The vite-tsconfig-paths plugin works with jsconfig.json too.

Monorepo and Advanced Scenarios

In monorepos, ensure your paths are relative to the workspace root:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@app/*": ["packages/app/src/*"],
      "@shared/*": ["packages/shared/src/*"]
    }
  }
}

For Windows users, always use forward slashes (/) in path configurations—both Vite and TypeScript normalize them correctly.

Build vs Development Discrepancies

If aliases work in development but fail during build:

  1. Check for case sensitivity issues (especially on Linux/macOS)
  2. Ensure baseUrl is set correctly
  3. Verify all aliased paths exist in your build output
  4. Check that your build tool preserves the alias configuration

Quick Reference: Manual vs vite-tsconfig-paths

AspectManual Configurationvite-tsconfig-paths
Setup complexityTwo files to maintainOne file only
ControlFull customizationFollows tsconfig.json
MaintenanceManual synchronizationAutomatic
Best forSimple projects, specific requirementsMost projects, monorepos
PerformanceSlightly faster (no plugin overhead)Negligible difference

Conclusion

Fixing Vite Failed to resolve import errors comes down to aligning module resolution between Vite and TypeScript. The manual method gives you precise control over both configurations, while vite-tsconfig-paths eliminates synchronization headaches entirely.

For most projects, start with vite-tsconfig-paths—it’s simpler and prevents configuration drift. Switch to manual configuration only when you need different aliasing strategies between development and production, or when working with unusual build setups that require custom resolution logic.

FAQs

Vite and TypeScript use separate configuration systems. TypeScript reads tsconfig.json for type checking while Vite uses vite.config.ts for bundling. Both need matching path alias configurations to work correctly.

Yes, create a jsconfig.json file with your path mappings and configure Vite aliases manually or use vite-tsconfig-paths which supports both jsconfig.json and tsconfig.json files.

Modern Vite projects use ES modules where __dirname isn't available. Use import.meta.url with fileURLToPath for ESM compatibility, or __dirname only in CommonJS environments.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay