search
Javascript star Featured

[SOLVED] Error Module parse failed: Unexpected token

Learn how to fix the 'Module parse failed: Unexpected token' error in JavaScript. Complete guide with solutions for JSX, TypeScript, and bundler configurations.

person By Gautam Sharma
calendar_today January 2, 2026
schedule 12 min read
JavaScript Error Handling Bundlers JSX TypeScript Webpack

The ‘Module parse failed: Unexpected token’ error is a common issue developers encounter when JavaScript bundlers like Webpack, Vite, or Babel cannot parse certain syntax in your code. This error typically occurs when the parser encounters syntax it doesn’t recognize or isn’t configured to handle.

This comprehensive guide provides complete solutions to resolve the module parse failed error with practical examples and bundler configuration techniques.


Understanding the Module Parse Failed Error

JavaScript bundlers parse code to understand its structure and dependencies. When they encounter syntax they can’t process, they throw this error. Common causes include:

  • JSX syntax without proper Babel configuration
  • TypeScript code without TypeScript loader
  • ES6+ features without transpilation
  • CSS-in-JS or template literals with special syntax
  • Import/export syntax issues

Common Error Messages:

  • Module parse failed: Unexpected token <
  • Module parse failed: Unexpected token .
  • Module parse failed: Unexpected token :
  • Module parse failed: Unexpected token =>
  • SyntaxError: Unexpected token

Common Causes and Solutions

1. JSX Syntax Without Proper Configuration

The most common cause is JSX syntax without Babel configuration.

❌ Problem Scenario:

// ❌ This will fail without proper JSX configuration
function App() {
  return (
    <div>
      <h1>Hello World</h1>
      <p>This JSX will cause a parse error</p>
    </div>
  );
}

✅ Solution: Configure Babel for JSX

// .babelrc or babel.config.js
{
  "presets": [
    ["@babel/preset-env", {
      "targets": {
        "node": "current"
      }
    }],
    ["@babel/preset-react", {
      "runtime": "automatic" // React 17+ JSX transform
    }]
  ]
}

2. TypeScript Without Proper Loader

Using TypeScript without proper configuration causes parsing errors.

❌ Problem Scenario:

// ❌ This will fail without TypeScript loader
interface User {
  name: string;
  age: number;
}

const user: User = {
  name: 'John',
  age: 30
};

✅ Solution: Configure TypeScript

// babel.config.js for TypeScript
{
  "presets": [
    ["@babel/preset-env", {
      "targets": {
        "node": "current"
      }
    }],
    ["@babel/preset-react", {
      "runtime": "automatic"
    }],
    "@babel/preset-typescript"
  ]
}

Solution 1: Webpack Configuration

Configure Webpack properly to handle different syntax types.

Webpack Configuration:

// webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        // ✅ Handle JavaScript and JSX files
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', {
                targets: {
                  browsers: ['last 2 versions']
                }
              }],
              ['@babel/preset-react', {
                runtime: 'automatic'
              }]
            ]
          }
        }
      },
      {
        // ✅ Handle TypeScript files
        test: /\.(ts|tsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'ts-loader',
          options: {
            transpileOnly: true
          }
        }
      },
      {
        // ✅ Handle CSS files
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        // ✅ Handle image files
        test: /\.(png|jpe?g|gif|svg)$/i,
        type: 'asset/resource'
      }
    ]
  },
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx', '.json']
  },
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    port: 3000,
  }
};

Advanced Webpack Configuration:

// webpack.config.js with advanced parsing
const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', {
                targets: '> 0.25%, not dead',
                useBuiltIns: 'usage',
                corejs: 3
              }],
              ['@babel/preset-react', {
                runtime: 'automatic'
              }]
            ],
            plugins: [
              '@babel/plugin-syntax-jsx',
              '@babel/plugin-proposal-class-properties',
              '@babel/plugin-proposal-object-rest-spread'
            ]
          }
        }
      },
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                '@babel/preset-typescript',
                ['@babel/preset-react', { runtime: 'automatic' }]
              ]
            }
          },
          'ts-loader'
        ]
      }
    ]
  },
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx'],
    alias: {
      '@': path.resolve(__dirname, 'src'),
    }
  }
};

Solution 2: Babel Configuration

Configure Babel to handle modern JavaScript syntax.

Babel Configuration:

// babel.config.js
module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          browsers: ['> 1%', 'last 2 versions', 'not ie <= 8']
        },
        modules: 'auto',
        useBuiltIns: 'usage',
        corejs: 3
      }
    ],
    [
      '@babel/preset-react',
      {
        runtime: 'automatic' // React 17+ JSX transform
      }
    ]
  ],
  plugins: [
    // Additional plugins for specific syntax
    '@babel/plugin-syntax-dynamic-import',
    '@babel/plugin-syntax-import-meta',
    '@babel/plugin-proposal-class-properties',
    '@babel/plugin-proposal-json-strings',
    [
      '@babel/plugin-proposal-decorators',
      {
        legacy: true
      }
    ],
    '@babel/plugin-proposal-function-sent',
    '@babel/plugin-proposal-export-namespace-from',
    '@babel/plugin-proposal-numeric-separator',
    '@babel/plugin-proposal-throw-expressions'
  ]
};

Package.json Babel Setup:

{
  "name": "my-project",
  "version": "1.0.0",
  "scripts": {
    "build": "webpack --mode production",
    "dev": "webpack serve --mode development",
    "test": "jest"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@babel/preset-env": "^7.20.0",
    "@babel/preset-react": "^7.18.0",
    "@babel/preset-typescript": "^7.18.0",
    "@babel/plugin-syntax-jsx": "^7.18.0",
    "@babel/plugin-proposal-class-properties": "^7.18.0",
    "babel-loader": "^9.1.0",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.0",
    "webpack-dev-server": "^4.11.0"
  }
}

Solution 3: TypeScript Configuration

Configure TypeScript properly for module parsing.

TypeScript Configuration:

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "node",
    "lib": [
      "dom",
      "dom.iterable",
      "es6"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "moduleDetection": "force",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx", // For React 17+
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  "include": [
    "src"
  ],
  "exclude": [
    "node_modules"
  ]
}

TypeScript with Babel:

// babel.config.js for TypeScript + Babel
module.exports = {
  presets: [
    ['@babel/preset-env', {
      targets: {
        browsers: ['> 1%', 'last 2 versions']
      }
    }],
    ['@babel/preset-react', {
      runtime: 'automatic'
    }],
    '@babel/preset-typescript'
  ],
  plugins: [
    '@babel/plugin-transform-typescript',
    '@babel/plugin-syntax-jsx'
  ]
};

Solution 4: Vite Configuration

Configure Vite for proper module parsing.

Vite Configuration:

// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { resolve } from 'path';

export default defineConfig({
  plugins: [react()],
  
  resolve: {
    alias: {
      '@': resolve(__dirname, './src'),
    },
  },
  
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          'react-vendor': ['react', 'react-dom'],
        },
      },
    },
  },
  
  // ✅ Handle different file types
  optimizeDeps: {
    include: [
      'react',
      'react-dom',
    ],
  },
});

Vite with TypeScript:

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { resolve } from 'path';

export default defineConfig({
  plugins: [react()],
  
  resolve: {
    alias: {
      '@': resolve(__dirname, './src'),
    },
  },
  
  esbuild: {
    // ✅ Handle JSX in .js files
    jsx: 'automatic',
    jsxFactory: 'React.createElement',
    jsxFragment: 'React.Fragment',
  },
  
  optimizeDeps: {
    include: [
      'react',
      'react-dom',
      'react/jsx-runtime',
    ],
  },
});

Solution 5: Handling Different File Types

Configure your build system to handle various file types properly.

CSS-in-JS and Styled Components:

// webpack.config.js for CSS-in-JS
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              '@babel/preset-env',
              ['@babel/preset-react', { runtime: 'automatic' }]
            ],
            plugins: [
              'babel-plugin-styled-components' // For styled-components
            ]
          }
        }
      }
    ]
  }
};

Template Literals and GraphQL:

// webpack.config.js for GraphQL and template literals
module.exports = {
  module: {
    rules: [
      {
        test: /\.(graphql|gql)$/,
        exclude: /node_modules/,
        loader: 'graphql-tag/loader'
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              '@babel/preset-env',
              ['@babel/preset-react', { runtime: 'automatic' }]
            ],
            plugins: [
              'babel-plugin-graphql-tag' // For GraphQL template literals
            ]
          }
        }
      }
    ]
  }
};

Solution 6: Environment-Specific Parsing

Handle parsing differently based on environment.

Environment-Aware Configuration:

// webpack.config.js with environment awareness
const path = require('path');

module.exports = (env, argv) => {
  const isProduction = argv.mode === 'production';
  
  return {
    mode: argv.mode || 'development',
    entry: './src/index.js',
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: isProduction ? '[name].[contenthash].js' : '[name].js',
    },
    module: {
      rules: [
        {
          test: /\.(js|jsx)$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    targets: isProduction 
                      ? { browsers: ['> 1%', 'not dead'] }
                      : { node: 'current' },
                    modules: isProduction ? 'auto' : false // Don't transform modules in development
                  }
                ],
                ['@babel/preset-react', { runtime: 'automatic' }]
              ],
              plugins: [
                // Only include development plugins in development
                ...(argv.mode !== 'production' ? [
                  'react-refresh/babel'
                ] : [])
              ]
            }
          }
        }
      ]
    },
    resolve: {
      extensions: ['.js', '.jsx', '.json']
    },
    devtool: isProduction ? 'source-map' : 'eval-source-map'
  };
};

Solution 7: Error Handling and Debugging

Implement proper error handling for parsing issues.

Debugging Configuration:

// webpack.config.js with enhanced error reporting
const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                ['@babel/preset-env', { targets: { node: 'current' } }],
                ['@babel/preset-react', { runtime: 'automatic' }]
              ],
              cacheDirectory: true, // Enable caching for faster builds
            }
          }
        ],
        // ✅ Add parser options for better error reporting
        parser: {
          amd: false,
          commonjs: false,
          system: false,
          harmony: true,
          requireInclude: false,
          requireEnsure: false,
          requireContext: false,
          browserify: false,
          node: false
        }
      }
    ]
  },
  resolve: {
    extensions: ['.js', '.jsx', '.json']
  },
  stats: {
    // ✅ Detailed error reporting
    errorDetails: true,
    moduleTrace: true,
    reasons: true
  }
};

Error Reporting Utilities:

// utils/parsingErrorHandler.js
class ParsingErrorHandler {
  static handleParseError(error, filePath) {
    console.error(`Parse error in file: ${filePath}`);
    console.error('Error details:', error.message);
    
    // ✅ Provide helpful suggestions
    const suggestions = this.generateSuggestions(error, filePath);
    console.error('Possible solutions:', suggestions);
    
    throw error;
  }

  static generateSuggestions(error, filePath) {
    const suggestions = [];
    
    if (error.message.includes('Unexpected token')) {
      if (filePath.endsWith('.jsx') || filePath.includes('jsx')) {
        suggestions.push('Ensure Babel is configured for JSX parsing');
        suggestions.push('Check if @babel/preset-react is installed and configured');
      }
      
      if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
        suggestions.push('Ensure TypeScript loader is properly configured');
        suggestions.push('Check if @babel/preset-typescript is installed');
      }
      
      if (error.message.includes('<')) {
        suggestions.push('This is likely JSX syntax - configure React preset');
      }
      
      if (error.message.includes('=>')) {
        suggestions.push('Arrow function syntax might need @babel/preset-env');
      }
    }
    
    return suggestions;
  }
}

// Usage in build process
function buildWithParsingErrorHandling() {
  try {
    // Build process here
  } catch (error) {
    if (error.message.includes('Module parse failed')) {
      ParsingErrorHandler.handleParseError(error, error.module?.resource);
    }
    throw error;
  }
}

Solution 8: Testing and Validation

Test your parsing configuration to ensure it works properly.

Jest Configuration:

// jest.config.js
module.exports = {
  testEnvironment: 'jsdom',
  transform: {
    '^.+\\.(js|jsx)$': ['babel-jest', {
      presets: [
        ['@babel/preset-env', { targets: { node: 'current' } }],
        ['@babel/preset-react', { runtime: 'automatic' }]
      ]
    }],
    '^.+\\.(ts|tsx)$': ['ts-jest', {
      tsconfig: '<rootDir>/tsconfig.json'
    }]
  },
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1'
  },
  testMatch: [
    '**/__tests__/**/*.(spec|test).{js,jsx,ts,tsx}',
  ],
  setupFilesAfterEnv: ['<rootDir>/src/setupTests.js']
};

Test Examples:

// __tests__/parsing.test.js
import React from 'react';
import { render } from '@testing-library/react';
import App from '../src/App';

describe('Module parsing', () => {
  test('should parse JSX without errors', () => {
    const { getByText } = render(<App />);
    expect(getByText(/Hello/i)).toBeInTheDocument();
  });

  test('should handle ES6+ syntax', () => {
    const obj = { a: 1, b: 2 };
    const { c, ...rest } = { ...obj, c: 3 };
    expect(rest).toEqual({ a: 1, b: 2 });
  });
});

Solution 9: Performance Optimization

Optimize parsing for better performance.

Optimized Configuration:

// webpack.config.js with performance optimizations
const path = require('path');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js',
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    targets: '> 0.25%, not dead',
                    useBuiltIns: 'usage',
                    corejs: 3,
                    modules: false // Keep ES modules for tree shaking
                  }
                ],
                ['@babel/preset-react', { runtime: 'automatic' }]
              ],
              cacheDirectory: true, // Cache babel transformations
              cacheCompression: false,
              compact: true, // Minimize output
            }
          }
        ]
      }
    ]
  },
  resolve: {
    extensions: ['.js', '.jsx', '.json'],
    modules: [path.resolve(__dirname, 'src'), 'node_modules']
  },
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        }
      }
    }
  }
};

Security Considerations

Safe Parsing Configuration:

// utils/safeParser.js
class SafeParser {
  static validateCode(code, allowedSyntax = []) {
    // ✅ Validate code before parsing
    const dangerousPatterns = [
      /eval\s*\(/,
      /new\s+Function\s*\(/,
      /setTimeout\s*\([^,]*,?\s*["'].*["']\s*\)/,
      /setInterval\s*\([^,]*,?\s*["'].*["']\s*\)/,
    ];

    for (const pattern of dangerousPatterns) {
      if (pattern.test(code)) {
        throw new Error(`Potentially dangerous code detected: ${pattern}`);
      }
    }

    return true;
  }

  static async parseWithValidation(code, filePath) {
    try {
      // ✅ Validate code first
      this.validateCode(code);
      
      // ✅ Then parse with appropriate tools
      // This is a simplified example - in practice, use proper AST parsing
      return eval(code); // Never do this in production!
    } catch (error) {
      console.error(`Security validation failed for ${filePath}:`, error);
      throw error;
    }
  }
}

Common Mistakes to Avoid

1. Missing Babel Configuration:

// ❌ Don't do this
// Using JSX without Babel configuration
function App() {
  return <div>Hello</div>; // Will cause parse error
}

2. Incorrect File Extensions:

// ❌ Don't do this
// Using .js extension for TypeScript code without proper loader
const user: User = { name: 'John' }; // Parse error without TS loader

3. Misconfigured Loaders:

// ❌ Don't do this
// Babel loader not configured for JSX
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader' // Missing presets for JSX
      }
    ]
  }
};

Alternative Solutions

Using React DevTools:

// Component with parsing validation
function ParsingValidator() {
  const [isValid, setIsValid] = useState(false);
  
  useEffect(() => {
    try {
      // Validate parsing
      setIsValid(true);
    } catch (error) {
      console.error('Parsing validation failed:', error);
      setIsValid(false);
    }
  }, []);

  return (
    <div data-testid="parsing-validator">
      <p>Parsing Status: {isValid ? 'Valid' : 'Invalid'}</p>
    </div>
  );
}

Feature Detection:

// Check for parsing features
function checkParsingSupport() {
  try {
    // Try to parse modern syntax
    eval('const test = () => true;');
    return true;
  } catch {
    return false;
  }
}

Troubleshooting Checklist

When encountering the module parse failed error:

  1. Check Babel Configuration: Ensure proper presets for JSX/TS
  2. Verify File Extensions: Confirm correct extensions in imports
  3. Review Loaders: Check webpack/vite loaders are properly configured
  4. Test Syntax: Verify the problematic syntax is supported
  5. Check Dependencies: Ensure all required packages are installed
  6. Validate Paths: Confirm file paths are correct
  7. Review Error Details: Look for specific token information

Conclusion

The ‘Module parse failed: Unexpected token’ error occurs when JavaScript bundlers encounter syntax they cannot parse. By understanding the parsing requirements and configuring your build tools properly, you can resolve these errors and ensure your code is processed correctly.

The key to resolving this error is proper configuration of your build tools, including Babel presets for JSX, TypeScript loaders, and appropriate file type handling. Whether you’re working with React, TypeScript, or modern JavaScript features, the solutions provided in this guide will help you configure your parsing setup correctly.

Remember to always validate your build configurations, use appropriate presets and plugins, and test your setup thoroughly to ensure smooth parsing across all your project files.

Gautam Sharma

About Gautam Sharma

Full-stack developer and tech blogger sharing coding tutorials and best practices

Related Articles

Javascript

How to Handle & Fix Failed to resolve import Error Tutorial

Learn how to fix 'failed to resolve import' errors in JavaScript. Complete guide with solutions for ES6 modules, Node.js, and bundler configurations.

January 2, 2026
Javascript

How to Solve You may need an appropriate loader Error

Learn how to fix the 'You may need an appropriate loader' error in JavaScript bundlers. Complete guide with solutions for Webpack, Vite, and module loaders.

January 2, 2026
Javascript

How to Fix __dirname is not defined Error: Node.js & JS Tutorial

Learn how to resolve the __dirname not defined error in Node.js and browser environments. Complete guide with solutions for ES6 modules and modern JavaScript.

January 2, 2026