No articles found
Try different keywords or browse our categories
Fix: 500 Internal Server Error after deploy
Complete guide to fix '500 Internal Server Error after deploy'. Learn how to troubleshoot and resolve server errors after deployment.
The ‘500 Internal Server Error after deploy’ occurs when your application works locally but fails in the production environment after deployment, typically due to environment differences, missing dependencies, or configuration issues.
How the Error Happens
This error typically occurs when:
- Environment variables are missing in production
- Dependencies not properly installed in production
- File paths that work locally don’t work in production
- Database connections fail in production environment
- Permission issues with deployed files
- Build process issues in production
Solution 1: Check Server Logs
# ✅ Check deployment logs
# For Vercel
vercel logs your-domain.vercel.app
# For Netlify
netlify logs:tail
# For Heroku
heroku logs --tail -a your-app-name
# ✅ For self-hosted servers
tail -f /var/log/nginx/error.log
# OR
journalctl -u your-app-service -f
// ✅ Add comprehensive error logging
// app.js
app.use((err, req, res, next) => {
console.error('Server Error:', {
message: err.message,
stack: process.env.NODE_ENV === 'development' ? err.stack : undefined,
url: req.url,
method: req.method,
timestamp: new Date().toISOString(),
userAgent: req.get('User-Agent'),
ip: req.ip
});
res.status(500).json({
error: 'Internal Server Error',
...(process.env.NODE_ENV === 'development' && { details: err.message })
});
});
Solution 2: Verify Environment Variables
// ✅ Proper environment variable handling
// config/env.js
function getEnvVar(name, defaultValue = null) {
const value = process.env[name];
if (value === undefined || value === '') {
if (defaultValue !== null) {
console.warn(`Environment variable ${name} not set, using default`);
return defaultValue;
}
if (process.env.NODE_ENV === 'production') {
throw new Error(`Required environment variable ${name} is not set`);
}
return null;
}
return value;
}
// ✅ Usage
const dbUrl = getEnvVar('DATABASE_URL', 'mongodb://localhost:27017/myapp');
const port = getEnvVar('PORT', '3000');
const jwtSecret = getEnvVar('JWT_SECRET');
// ✅ Ensure .env.example exists with all required variables
{
"DATABASE_URL": "your_database_connection_string",
"JWT_SECRET": "your_jwt_secret",
"NODE_ENV": "production",
"PORT": "3000"
}
Solution 3: Verify Dependencies
// ✅ In package.json, ensure production dependencies are correct
{
"name": "my-app",
"scripts": {
"build": "npm run build:client && npm run build:server",
"start": "node dist/server.js",
"deploy": "npm ci --only=production && npm run start"
},
"dependencies": {
"express": "^4.18.0",
"mongoose": "^7.0.0",
"bcryptjs": "^2.4.3"
},
"devDependencies": {
"nodemon": "^2.0.0",
"@types/node": "^18.0.0"
}
}
# ✅ Verify dependencies are properly installed
npm ci --only=production # ✅ Clean install of production dependencies only
npm audit # ✅ Check for security vulnerabilities
npm outdated # ✅ Check for outdated packages
Solution 4: Check File Permissions and Paths
// ✅ Handle file paths properly for different environments
const path = require('path');
// ✅ Use path.join for cross-platform compatibility
const uploadsDir = path.join(__dirname, '..', 'uploads');
const configPath = path.join(process.cwd(), 'config', 'app.json');
// ✅ Check if directories exist and are writable
const fs = require('fs');
function ensureDirectoryExists(dirPath) {
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
console.log(`Created directory: ${dirPath}`);
}
// ✅ Check if directory is writable
try {
fs.accessSync(dirPath, fs.constants.W_OK);
return true;
} catch (err) {
console.error(`Directory not writable: ${dirPath}`);
return false;
}
}
// ✅ Proper static file serving
app.use('/uploads', express.static(path.join(__dirname, '..', 'uploads')));
// ✅ Handle static files with error checking
app.use('/static', (req, res, next) => {
const filePath = path.join(__dirname, '..', 'static', req.path);
// ✅ Check if file exists before serving
fs.access(filePath, fs.constants.R_OK, (err) => {
if (err) {
console.error(`File not accessible: ${filePath}`);
return res.status(404).send('File not found');
}
next();
});
});
Solution 5: Database Connection Handling
// ✅ Robust database connection with error handling
const mongoose = require('mongoose');
async function connectToDatabase() {
const dbUrl = process.env.DATABASE_URL;
if (!dbUrl) {
throw new Error('DATABASE_URL environment variable is not set');
}
try {
await mongoose.connect(dbUrl, {
useNewUrlParser: true,
useUnifiedTopology: true,
serverSelectionTimeoutMS: 5000, // ✅ Timeout after 5s instead of 30s
});
console.log('Database connected successfully');
} catch (error) {
console.error('Database connection failed:', error);
throw error;
}
}
// ✅ Initialize database connection
connectToDatabase().catch(err => {
console.error('Failed to connect to database:', err);
process.exit(1); // ✅ Exit if database connection fails
});
Solution 6: Implement Health Checks
// ✅ Add health check endpoint
app.get('/health', async (req, res) => {
try {
// ✅ Check database connection
const dbOk = mongoose.connection.readyState === 1;
// ✅ Check other services
const checks = {
database: dbOk,
uptime: process.uptime(),
timestamp: new Date().toISOString(),
environment: process.env.NODE_ENV,
version: process.env.npm_package_version || 'unknown'
};
const isHealthy = Object.values(checks).every(check => check !== false);
res.status(isHealthy ? 200 : 503).json({
status: isHealthy ? 'healthy' : 'unhealthy',
checks
});
} catch (error) {
res.status(500).json({
status: 'unhealthy',
error: error.message
});
}
});
Solution 7: Proper Error Handling Middleware
// ✅ Comprehensive error handling middleware
app.use((error, req, res, next) => {
console.error('Unhandled error:', {
error: error.message,
stack: error.stack,
url: req.url,
method: req.method,
timestamp: new Date().toISOString()
});
// ✅ Don't expose internal errors in production
if (process.env.NODE_ENV === 'production') {
res.status(500).json({
error: 'Internal Server Error',
message: 'An unexpected error occurred'
});
} else {
res.status(500).json({
error: 'Internal Server Error',
message: error.message,
stack: error.stack
});
}
});
// ✅ Catch unhandled promise rejections
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
// ✅ Application specific logging, throwing an error, or other logic here
});
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', error);
process.exit(1); // ✅ Exit process after logging
});
Solution 8: Deployment-Specific Configuration
// ✅ Environment-specific configuration
const config = {
development: {
port: 3000,
dbUrl: 'mongodb://localhost:27017/myapp_dev',
jwtSecret: 'dev-secret-key',
logging: true
},
production: {
port: process.env.PORT || 80,
dbUrl: process.env.DATABASE_URL,
jwtSecret: process.env.JWT_SECRET,
logging: false
}
};
const env = process.env.NODE_ENV || 'development';
const appConfig = config[env];
// ✅ Validate required configuration
function validateConfig(config) {
const required = ['port', 'dbUrl', 'jwtSecret'];
const missing = required.filter(key => !config[key]);
if (missing.length > 0) {
throw new Error(`Missing required configuration: ${missing.join(', ')}`);
}
}
validateConfig(appConfig);
Solution 9: Build Process Verification
// ✅ In package.json, ensure build process is correct
{
"scripts": {
"prebuild": "npm run clean",
"build": "rimraf dist && tsc && cp -r public dist/",
"postbuild": "npm run verify-build",
"verify-build": "node scripts/verify-build.js",
"start": "NODE_ENV=production node dist/server.js",
"dev": "NODE_ENV=development nodemon src/server.ts"
}
}
// ✅ Build verification script (scripts/verify-build.js)
const fs = require('fs');
const path = require('path');
const requiredFiles = [
'dist/server.js',
'dist/app.js',
'package.json'
];
function verifyBuild() {
console.log('Verifying build...');
for (const file of requiredFiles) {
const filePath = path.join(process.cwd(), file);
if (!fs.existsSync(filePath)) {
console.error(`❌ Required file missing: ${file}`);
process.exit(1);
}
console.log(`✅ ${file} exists`);
}
console.log('✅ Build verification passed');
}
verifyBuild();
Prevention Tips
- Test deployment locally: Use Docker or similar to simulate production
- Use environment-specific configs: Different settings for dev/prod
- Implement comprehensive logging: Capture all errors and events
- Monitor resource usage: Watch CPU, memory, and disk usage
- Use health checks: Implement endpoints to monitor app status
- Validate configurations: Check all required settings before starting
- Handle errors gracefully: Never let unhandled errors crash the app
- Monitor dependencies: Keep packages updated and secure
When to Contact Support
Contact your hosting provider when:
- Following all troubleshooting steps still results in 500 errors
- Suspected infrastructure issues on their side
- Need to increase resource limits
- Encountering platform-specific configuration issues
- Experiencing billing-related deployment problems
Related Articles
Fix: Build succeeded but site shows blank page in React Angular Vue
Complete guide to fix blank page issues after successful builds in React, Angular, and Vue applications. Learn how to debug and resolve blank page errors with practical solutions.
Fix: Access is denied error in Windows
Complete guide to fix 'Access is denied' error in Windows. Learn how to resolve permission issues, UAC problems, and file access restrictions.
Fix: The process cannot access the file because it is being used by another process
Complete guide to fix 'The process cannot access the file because it is being used by another process' error. Learn multiple solutions for Windows file access issues.