This error occurs when a web application tries to make a cross-origin HTTP request, but the server does not allow requests from the requesting origin. Browsers enforce CORS (Cross-Origin Resource Sharing) to protect users from potentially malicious cross-origin requests.
This error indicates that your web application is attempting to make an HTTP request from one origin (domain, protocol, or port) to a different origin, and the browser has blocked it due to the Same-Origin Policy. For example, if your frontend runs on http://localhost:3000 and tries to fetch data from http://localhost:5000, the browser will block this unless the backend server explicitly allows it. CORS is a security mechanism that requires servers to send specific HTTP headers (like Access-Control-Allow-Origin) to inform the browser which origins are permitted to access resources. Without these headers, browsers will refuse to expose the response to the requesting script, resulting in this error. The error commonly appears when developing full-stack applications where the frontend and backend run on different ports during development, or when a production app makes API calls to a different domain.
The cors npm package provides Express middleware that automatically handles CORS headers and preflight requests.
npm install corsOr with yarn:
yarn add corsFor quick development testing, enable CORS for all origins and routes. Import cors and add it as middleware before your routes:
const express = require('express');
const cors = require('cors');
const app = express();
// Enable CORS for all routes and origins
app.use(cors());
app.get('/api/data', (req, res) => {
res.json({ message: 'CORS is enabled' });
});
app.listen(5000, () => {
console.log('Server running on port 5000');
});This allows requests from any origin. Note: This is suitable for development but not recommended for production.
For production, restrict CORS to specific trusted origins. Configure the cors middleware with an origin whitelist:
const express = require('express');
const cors = require('cors');
const app = express();
const corsOptions = {
origin: ['https://yourdomain.com', 'https://app.yourdomain.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true, // Allow cookies and credentials
optionsSuccessStatus: 200 // Some legacy browsers choke on 204
};
app.use(cors(corsOptions));
app.get('/api/data', (req, res) => {
res.json({ message: 'CORS configured for specific origins' });
});
app.listen(5000);For dynamic origin validation based on environment:
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',') || ['http://localhost:3000'];
const corsOptions = {
origin: function (origin, callback) {
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
}
};
app.use(cors(corsOptions));Complex requests (using methods like PUT, DELETE, or custom headers) trigger a preflight OPTIONS request. Ensure your server handles these:
const express = require('express');
const cors = require('cors');
const app = express();
// Enable pre-flight across all routes
app.options('*', cors());
// Apply CORS middleware
app.use(cors());
app.delete('/api/resource/:id', (req, res) => {
// This route now properly handles preflight
res.json({ message: 'Resource deleted' });
});
app.listen(5000);If implementing CORS manually without the package:
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://yourdomain.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Credentials', 'true');
// Handle preflight
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});After configuring CORS, verify the headers are being sent correctly:
1. Open browser DevTools (F12)
2. Go to the Network tab
3. Make the cross-origin request
4. Click on the request to inspect headers
5. Check the Response Headers section for:
- Access-Control-Allow-Origin: <your-origin>
- Access-Control-Allow-Methods: ...
- Access-Control-Allow-Headers: ...
For preflight requests, look for an OPTIONS request that precedes your actual request. It should return a 200 or 204 status with proper CORS headers.
If headers are missing, ensure the cors middleware is applied before your route handlers and that no other middleware is interfering.
Security Considerations:
Never use origin: '*' (wildcard) with credentials: true in production. Browsers will reject this configuration. If you need to support credentials (cookies, authorization headers), you must specify exact origins.
Proxy Alternative for Development:
During development, you can bypass CORS by configuring a proxy in your frontend build tool instead of enabling CORS on the backend. For example, in package.json for Create React App:
{
"proxy": "http://localhost:5000"
}This makes the dev server proxy API requests to your backend, avoiding cross-origin issues entirely.
Performance Optimization:
Preflight requests add latency. You can cache preflight responses with the Access-Control-Max-Age header to reduce overhead:
const corsOptions = {
origin: 'https://yourdomain.com',
maxAge: 86400 // Cache preflight for 24 hours
};Multiple Origin Patterns:
Use regex patterns to allow multiple subdomains:
const corsOptions = {
origin: /\.yourdomain\.com$/,
credentials: true
};This allows app.yourdomain.com, api.yourdomain.com, etc., while blocking unrelated origins.
Error: Listener already called (once event already fired)
EventEmitter listener already called with once()
Error: EACCES: permission denied, open '/root/file.txt'
EACCES: permission denied
Error: Invalid encoding specified (stream encoding not supported)
How to fix Invalid encoding error in Node.js readable streams
Error: EINVAL: invalid argument, open
EINVAL: invalid argument, open
TypeError: readableLength must be a positive integer (stream config)
TypeError: readableLength must be a positive integer in Node.js streams