No articles found
Try different keywords or browse our categories
Fix: Uncaught SyntaxError: Unexpected token '<' Error in Javascript
Learn how to fix the 'Uncaught SyntaxError: Unexpected token <' error in JavaScript applications. This comprehensive guide covers HTML responses, import issues, and best practices.
The ‘Uncaught SyntaxError: Unexpected token ’<” error is a common JavaScript issue that occurs when the browser receives an HTML response instead of the expected JavaScript code. This error typically happens when trying to import or load a JavaScript file that returns HTML (usually a 404 error page or server error page) instead of the actual JavaScript content.
This comprehensive guide explains what causes this error, why it happens, and provides multiple solutions to fix it in your JavaScript projects with clean code examples and directory structure.
What is the Unexpected token ’<’ Error?
The “Uncaught SyntaxError: Unexpected token ’<’” error occurs when:
- A JavaScript file request returns HTML instead of JavaScript
- The server returns an error page (404, 500, etc.) instead of the requested file
- Import paths are incorrect and resolve to HTML pages
- Module bundler configuration issues
- Server routing conflicts with static file serving
Common Error Messages:
Uncaught SyntaxError: Unexpected token '<'SyntaxError: Unexpected token '<' in JSON at position 0Uncaught SyntaxError: Unexpected token '<' in main.jsFailed to load module script: The server responded with a non-JavaScript MIME typeLoading module from “domain/file.js” was blocked
Understanding the Problem
This error happens because JavaScript engines expect to parse JavaScript code, but they receive HTML instead. When the parser encounters the < character (which starts HTML tags), it throws a syntax error because < is not a valid JavaScript token.
Typical JavaScript Project Structure:
my-js-app/
├── package.json
├── webpack.config.js
├── src/
│ ├── main.js
│ ├── components/
│ │ ├── app.js
│ │ └── header.js
│ ├── utils/
│ │ └── helpers.js
│ └── styles/
├── public/
│ ├── index.html
│ └── assets/
├── dist/
└── node_modules/
Solution 1: Check File Paths and URLs
The most common cause is incorrect file paths that return HTML instead of JavaScript.
❌ With Incorrect Paths:
// ❌ Wrong import path - might return HTML 404 page
import { myFunction } from './non-existent-file.js'; // ❌ 404 error page returned as HTML
// ❌ Wrong path that resolves to index.html
import { app } from '../index.js'; // ❌ This might load index.html instead of JS file
// ❌ Wrong relative path
import { utils } from './utils/helpers'; // ❌ Missing .js extension might cause issues
✅ With Correct Paths:
main.js:
// ✅ Correct import paths
import { myFunction } from './utils/helpers.js'; // ✅ Correct path with extension
import { App } from './components/app.js'; // ✅ Correct path with extension
import { Header } from './components/header.js'; // ✅ Correct path with extension
// ✅ Use absolute paths when appropriate
import { config } from '/src/config/appConfig.js';
// ✅ Verify file exists before importing
// Make sure helpers.js exists in ./utils/ directory
Directory structure verification:
src/
├── utils/
│ └── helpers.js // ✅ File exists
├── components/
│ ├── app.js // ✅ File exists
│ └── header.js // ✅ File exists
└── main.js // ✅ Main file
Solution 2: Verify Server Configuration
Ensure your server properly serves JavaScript files with correct MIME types.
❌ Without Proper Server Configuration:
// ❌ Server returns HTML for JS requests
// Server configuration might route all requests to index.html
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html')); // ❌ This catches JS requests too
});
✅ With Proper Server Configuration:
server.js (Express):
const express = require('express');
const path = require('path');
const app = express();
// ✅ Serve static files first
app.use(express.static(path.join(__dirname, 'public')));
// ✅ API routes
app.get('/api/data', (req, res) => {
res.json({ message: 'API data' });
});
// ✅ Catch-all route for SPA (only for HTML routes)
app.get('*', (req, res) => {
// ✅ Only serve index.html for routes that don't match static files
if (req.path.endsWith('.js') || req.path.endsWith('.css')) {
res.status(404).send('File not found');
return;
}
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
For Webpack Dev Server:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
devServer: {
static: {
directory: path.join(__dirname, 'public'),
},
compress: true,
port: 3000,
historyApiFallback: {
// ✅ Properly configure fallback for SPA
rewrites: [
{ from: /^\/$/, to: '/index.html' },
{ from: /^\/subpage/, to: '/index.html' },
{ from: /^\/api/, to: context => context.parsedUrl.pathname } // ✅ Don't redirect API calls
]
}
}
};
Solution 3: Check Module Bundler Configuration
Ensure your module bundler is configured correctly for JavaScript imports.
❌ Without Proper Bundler Configuration:
// webpack.config.js - ❌ Missing proper module rules
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
// ❌ Missing module rules for JS files
};
✅ With Proper Bundler Configuration:
webpack.config.js:
const path = require('path');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
clean: true
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
{
test: /\.js$/,
enforce: 'pre',
use: ['source-map-loader']
}
]
},
resolve: {
extensions: ['.js', '.json']
},
mode: 'development'
};
package.json:
{
"name": "my-js-app",
"version": "1.0.0",
"scripts": {
"build": "webpack",
"dev": "webpack serve --mode development",
"start": "node server.js"
},
"dependencies": {
"express": "^4.18.0"
},
"devDependencies": {
"webpack": "^5.0.0",
"webpack-cli": "^4.0.0",
"webpack-dev-server": "^4.0.0",
"babel-loader": "^8.0.0",
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"source-map-loader": "^4.0.0"
}
}
Solution 4: Use Proper Import/Export Syntax
Ensure you’re using correct ES6 module syntax.
❌ With Incorrect Syntax:
// ❌ Missing file extension in some cases
import { myFunction } from './utils/helpers'; // ❌ Might cause issues
// ❌ Wrong export syntax
module.exports = { myFunction }; // ❌ CommonJS in ES6 context
// ❌ Wrong import syntax
const { myFunction } = require('./utils/helpers'); // ❌ CommonJS in browser
✅ With Correct Syntax:
utils/helpers.js:
// ✅ ES6 export syntax
export const myFunction = () => {
return 'Hello from helpers';
};
export const myVariable = 'Helper variable';
// ✅ Default export
export default {
name: 'Helpers Module',
version: '1.0.0'
};
main.js:
// ✅ ES6 import syntax with proper extensions
import helpers, { myFunction, myVariable } from './utils/helpers.js';
import { App } from './components/app.js';
// ✅ Dynamic imports for code splitting
const loadFeature = async () => {
const { Feature } = await import('./features/feature.js');
return Feature;
};
console.log(myFunction());
console.log(myVariable);
console.log(helpers.name);
Solution 5: Handle Dynamic Imports Properly
Ensure dynamic imports resolve to the correct files.
❌ With Dynamic Import Issues:
// ❌ Dynamic import with wrong path
const loadModule = async (moduleName) => {
const module = await import(`./modules/${moduleName}`); // ❌ Missing .js extension
return module;
};
✅ With Proper Dynamic Imports:
// ✅ Safe dynamic import with validation
const loadModule = async (moduleName) => {
// ✅ Validate module name to prevent path traversal
if (!/^[a-zA-Z0-9_-]+$/.test(moduleName)) {
throw new Error('Invalid module name');
}
try {
// ✅ Include file extension in dynamic import
const module = await import(`./modules/${moduleName}.js`);
return module;
} catch (error) {
console.error(`Failed to load module ${moduleName}:`, error);
throw error;
}
};
// ✅ Usage
loadModule('myFeature').then(module => {
// Use the loaded module
});
Solution 6: Check HTML Script Tags
Ensure script tags are properly configured for ES6 modules.
❌ With Incorrect Script Tags:
<!-- ❌ Missing type="module" or wrong src -->
<script src="./src/main"></script> <!-- ❌ Missing .js extension -->
<script src="./nonexistent.js"></script> <!-- ❌ File doesn't exist -->
✅ With Correct Script Tags:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My App</title>
</head>
<body>
<div id="app"></div>
<!-- ✅ Correct script tag for ES6 modules -->
<script type="module" src="./src/main.js"></script>
<!-- ✅ Alternative: inline module -->
<script type="module">
import { App } from './src/components/app.js';
// Initialize app
</script>
</body>
</html>
Solution 7: Implement Error Handling for Imports
Add proper error handling around import operations.
utils/safeImport.js:
// ✅ Safe import utility with error handling
class SafeImport {
static async load(modulePath) {
try {
// ✅ Validate path to prevent security issues
if (!this.isValidPath(modulePath)) {
throw new Error(`Invalid module path: ${modulePath}`);
}
const module = await import(modulePath);
return { success: true, module, error: null };
} catch (error) {
console.error(`Failed to load module ${modulePath}:`, error);
return { success: false, module: null, error: error.message };
}
}
static isValidPath(path) {
// ✅ Basic validation to prevent path traversal
return typeof path === 'string' &&
path.length > 0 &&
!path.includes('../') &&
(path.endsWith('.js') || path.endsWith('.mjs'));
}
}
// ✅ Usage example
const loadApp = async () => {
const result = await SafeImport.load('./src/components/app.js');
if (result.success) {
const { App } = result.module;
// Initialize the app
console.log('App loaded successfully');
} else {
console.error('Failed to load app:', result.error);
// Handle the error appropriately
}
};
Working Code Examples
Complete Error-Resilient Application Structure:
// src/main.js
import { App } from './components/app.js';
import { Header } from './components/header.js';
import { Footer } from './components/footer.js';
class Application {
constructor() {
this.modules = new Map();
this.init();
}
async init() {
try {
// ✅ Load modules with error handling
await this.loadModules();
this.render();
} catch (error) {
this.handleError(error);
}
}
async loadModules() {
const modulesToLoad = [
{ name: 'app', path: './components/app.js' },
{ name: 'header', path: './components/header.js' },
{ name: 'footer', path: './components/footer.js' }
];
for (const moduleInfo of modulesToLoad) {
try {
const module = await import(moduleInfo.path);
this.modules.set(moduleInfo.name, module);
console.log(`Module ${moduleInfo.name} loaded successfully`);
} catch (error) {
console.error(`Failed to load module ${moduleInfo.name}:`, error);
throw error;
}
}
}
render() {
const appDiv = document.getElementById('app');
if (!appDiv) {
throw new Error('App container not found');
}
const header = new (this.modules.get('header').Header)();
const footer = new (this.modules.get('footer').Footer)();
const app = new (this.modules.get('app').App)();
appDiv.innerHTML = `
<header>${header.render()}</header>
<main>${app.render()}</main>
<footer>${footer.render()}</footer>
`;
}
handleError(error) {
console.error('Application error:', error);
const appDiv = document.getElementById('app');
if (appDiv) {
appDiv.innerHTML = `
<div class="error-container">
<h2>Application Error</h2>
<p>${error.message}</p>
<button onclick="location.reload()">Reload Page</button>
</div>
`;
}
}
}
// ✅ Initialize application when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
new Application();
});
Component Example:
// src/components/app.js
export class App {
constructor() {
this.data = null;
}
async loadData() {
try {
// ✅ Safe fetch with error handling
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
this.data = await response.json();
} catch (error) {
console.error('Failed to load data:', error);
this.data = { error: true, message: error.message };
}
}
render() {
return `
<div class="app-container">
<h1>My Application</h1>
<div id="content">
${this.renderContent()}
</div>
</div>
`;
}
renderContent() {
if (!this.data) {
return '<p>Loading...</p>';
}
if (this.data.error) {
return `<p class="error">Error: ${this.data.message}</p>`;
}
return `<p>Data loaded successfully: ${JSON.stringify(this.data)}</p>`;
}
}
Build Configuration:
// webpack.config.js - Production-ready configuration
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
clean: true
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
targets: {
browsers: ['> 1%', 'last 2 versions']
}
}]
]
}
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
minify: {
removeComments: true,
collapseWhitespace: true
}
})
],
resolve: {
extensions: ['.js', '.json']
},
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
}
}
}
},
mode: 'production'
};
Best Practices for Import Management
1. Always Use File Extensions
// ✅ Always include file extensions
import { myFunction } from './utils/helpers.js';
2. Validate Import Paths
// ✅ Validate paths before importing
const isValidPath = (path) => {
return typeof path === 'string' &&
path.length > 0 &&
path.endsWith('.js');
};
3. Use Absolute Imports When Possible
// ✅ Use absolute imports from a configured base
import { utils } from '@/utils/helpers.js'; // With webpack alias configuration
4. Implement Error Boundaries
// ✅ Wrap import operations in try-catch
try {
const module = await import('./path/to/module.js');
} catch (error) {
console.error('Import failed:', error);
}
Debugging Steps
Step 1: Check Network Tab
# Open browser dev tools
# Go to Network tab
# Look for failed requests (404, 500, etc.)
# Check response content - should be JS, not HTML
Step 2: Verify File Paths
# Check if files exist at specified paths
ls -la src/utils/helpers.js
ls -la src/components/app.js
Step 3: Test Direct File Access
# Try accessing JS files directly in browser
# http://localhost:3000/src/utils/helpers.js
# Should return JS content, not HTML
Step 4: Check Server Response Headers
# Verify Content-Type header for JS files
curl -I http://localhost:3000/src/utils/helpers.js
# Should have Content-Type: application/javascript
Common Mistakes to Avoid
1. Missing File Extensions
// ❌ Don't forget file extensions in some contexts
import { myFunction } from './utils/helpers'; // ❌ Might cause issues
2. Wrong Server Configuration
// ❌ Don't route all requests to index.html
app.get('*', (req, res) => {
res.sendFile('index.html'); // ❌ Catches JS requests too
});
3. Incorrect Module Syntax
// ❌ Don't mix CommonJS and ES6 modules in browser
const myModule = require('./module'); // ❌ Won't work in browser
4. Dynamic Import Security Issues
// ❌ Don't allow arbitrary file paths in dynamic imports
const userInput = 'user-provided-string';
const module = await import(userInput); // ❌ Security risk
Performance Considerations
1. Optimize Bundle Size
// ✅ Use tree-shaking friendly imports
import { specificFunction } from 'library'; // ✅ Tree-shakable
// Instead of: import * as library from 'library';
2. Implement Code Splitting
// ✅ Use dynamic imports for code splitting
const loadFeature = async () => {
const { Feature } = await import('./feature.js');
return Feature;
};
Security Considerations
1. Validate Dynamic Import Paths
// ✅ Always validate paths for dynamic imports
const isValidModulePath = (path) => {
return /^[a-zA-Z0-9/_-]+\.js$/.test(path);
};
2. Prevent Path Traversal
// ✅ Prevent directory traversal in imports
if (path.includes('../') || path.includes('..\\')) {
throw new Error('Invalid path');
}
Testing Import Functionality
1. Unit Test Import Operations
// Using Jest or similar testing framework
describe('Module imports', () => {
test('should import module successfully', async () => {
const module = await import('./testModule.js');
expect(module).toBeDefined();
expect(typeof module.myFunction).toBe('function');
});
test('should handle import errors gracefully', async () => {
await expect(import('./nonexistent.js')).rejects.toThrow();
});
});
2. Test Build Process
// Test that build process creates correct file structure
test('build should create expected files', () => {
expect(fs.existsSync('dist/bundle.js')).toBe(true);
expect(fs.existsSync('dist/index.html')).toBe(true);
});
Alternative Solutions
1. Use Import Maps (Modern Browsers)
<!-- ✅ Use import maps for cleaner imports -->
<script type="importmap">
{
"imports": {
"utils": "./src/utils/index.js",
"components": "./src/components/index.js"
}
}
</script>
2. Use Bundler Aliases
// ✅ Webpack alias configuration
module.exports = {
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@utils': path.resolve(__dirname, 'src/utils')
}
}
};
Migration Checklist
- Verify all import paths are correct
- Check server configuration for static files
- Test that JS files return proper content type
- Validate module bundler configuration
- Add error handling around import operations
- Run build process to verify output
- Test in different browsers
- Update documentation for team members
Conclusion
The ‘Uncaught SyntaxError: Unexpected token <” error is a common JavaScript issue that occurs when HTML is returned instead of JavaScript code. By following the solutions provided in this guide—whether through proper file path management, server configuration, module bundler setup, or error handling—you can ensure your JavaScript applications load and execute correctly.
The key is to understand that this error indicates a server-side problem where HTML is being returned instead of the expected JavaScript file. With proper file management, server configuration, and import handling, your JavaScript applications will be more robust and reliable.
Remember to always verify file paths, configure your server properly for static file serving, implement proper error handling, and test thoroughly to ensure your applications handle import operations gracefully throughout their lifecycle.
Related Articles
How to Fix: Uncaught ReferenceError: require is not defined Error in Javascript
Learn how to fix the 'Uncaught ReferenceError: require is not defined' error in JavaScript. This comprehensive guide covers CommonJS, ES6 modules, and browser compatibility.
How to Fix “Uncaught TypeError: Cannot Read Properties of Undefined” in JavaScript
Learn how to fix the 'Uncaught TypeError: Cannot read properties of undefined' error in JavaScript. This comprehensive guide covers debugging, null checks, and best practices.
Fix: forEach is not a function JavaScript Error - Complete Solution Guide
Learn how to fix the 'forEach is not a function' JavaScript error. This guide covers all causes, solutions, and best practices for proper array method usage with step-by-step examples.