This error occurs when a client sends a request body that exceeds the server's configured size limit. By default, Express limits request bodies to 100KB, causing this error when larger payloads are sent.
The HTTP 413 Payload Too Large error is returned when the request entity (body) sent by the client exceeds the maximum size allowed by the server. This is a protective measure implemented by web servers and application frameworks to prevent memory exhaustion and denial-of-service attacks. In Node.js applications, particularly those using Express, this error commonly occurs because the default body-parser middleware limits request bodies to 100KB. When a client attempts to send data larger than this limit—such as uploading files, submitting large JSON payloads, or posting extensive form data—the server rejects the request with a 413 status code. The error can originate from multiple layers in your stack: the Node.js application itself (via Express body-parser limits), a reverse proxy like Nginx (via client_max_body_size), or other middleware in the request pipeline. Understanding which layer is enforcing the limit is crucial for applying the correct fix.
Configure Express middleware to accept larger payloads by setting the limit option. Place this configuration before defining your routes:
const express = require('express');
const app = express();
// Increase JSON body limit
app.use(express.json({ limit: '10mb' }));
// Increase URL-encoded body limit
app.use(express.urlencoded({
limit: '10mb',
extended: true,
parameterLimit: 50000
}));
// Your routes here
app.post('/api/data', (req, res) => {
// Handle request
});Adjust the limit value based on your needs. Common values: '1mb', '10mb', '50mb'. The parameterLimit controls the maximum number of URL parameters.
If you're handling file uploads, configure Multer's limits option to accept larger files:
const multer = require('multer');
const upload = multer({
storage: multer.diskStorage({
destination: 'uploads/',
filename: (req, file, cb) => {
cb(null, Date.now() + '-' + file.originalname);
}
}),
limits: {
fileSize: 20 * 1024 * 1024, // 20MB in bytes
files: 5 // Maximum number of files
}
});
app.post('/upload', upload.single('file'), (req, res) => {
res.json({ success: true });
});Handle Multer errors to provide clear feedback:
app.use((err, req, res, next) => {
if (err instanceof multer.MulterError) {
if (err.code === 'LIMIT_FILE_SIZE') {
return res.status(413).json({ error: 'File too large' });
}
}
next(err);
});If your Node.js application sits behind Nginx, increase the client_max_body_size directive. Edit your Nginx configuration:
server {
listen 80;
server_name example.com;
# Set maximum upload size to 20MB
client_max_body_size 20M;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}After modifying the configuration, test and reload Nginx:
# Test configuration
sudo nginx -t
# Reload Nginx
sudo systemctl reload nginxFor Apache, add to your VirtualHost or .htaccess:
LimitRequestBody 20971520Ensure body-parser middleware is configured BEFORE your route handlers and other middleware that process request bodies:
const express = require('express');
const app = express();
// CORRECT ORDER:
// 1. Body parser configuration (first)
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ limit: '10mb', extended: true }));
// 2. Other middleware
app.use(someOtherMiddleware());
// 3. Routes (last)
app.use('/api', apiRoutes);If you're using multiple body parsers, make sure limits are consistent across all of them.
Verify your configuration by testing with different payload sizes:
// test-payload.js
const axios = require('axios');
async function testPayload(sizeInMB) {
const data = {
payload: 'x'.repeat(sizeInMB * 1024 * 1024)
};
try {
const response = await axios.post('http://localhost:3000/api/test', data);
console.log(`✓ ${sizeInMB}MB payload succeeded`);
} catch (error) {
console.log(`✗ ${sizeInMB}MB payload failed: ${error.response?.status}`);
}
}
// Test with increasing sizes
testPayload(1);
testPayload(5);
testPayload(10);This helps identify the exact limit being enforced.
Security Considerations:
Always set payload limits deliberately rather than making them unlimited. Unrestricted payload sizes can lead to memory exhaustion, denial-of-service attacks, or storage issues. Choose limits based on your legitimate use cases.
Streaming for Large Files:
For very large file uploads (>50MB), consider using streaming approaches with libraries like Busboy or streaming multipart parsers. This prevents loading entire files into memory:
const busboy = require('busboy');
app.post('/stream-upload', (req, res) => {
const bb = busboy({ headers: req.headers });
bb.on('file', (name, file, info) => {
const saveTo = path.join('uploads', info.filename);
file.pipe(fs.createWriteStream(saveTo));
});
bb.on('finish', () => {
res.json({ success: true });
});
req.pipe(bb);
});Cloud Platform Limits:
Cloud platforms like AWS Lambda, Google Cloud Functions, and Azure Functions have hard limits on request body sizes (typically 6MB for Lambda). If you're deploying to these platforms, consider using direct S3/GCS uploads with presigned URLs instead of routing large files through your application.
Body-Parser vs Raw Body:
If you need complete control over request body handling, use express.raw() to access the raw buffer and implement custom size checks:
app.use(express.raw({
type: 'application/octet-stream',
limit: '50mb'
}));Monitoring:
Log 413 errors separately to identify whether you need to adjust limits or if clients are genuinely sending oversized payloads. This helps distinguish between legitimate use cases and potential attacks.
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