Common issues and solutions when working with Newgate.
Cause: The package is not installed or node_modules is corrupted.
Solution:
- Run
npm install newgatejs - Verify it exists in
package.jsondependencies. - Delete
node_modulesand runnpm installagain.
Cause: Permission issues on your system.
Solution:
- Use
sudo(not recommended). - Fix npm permissions: npm docs
- Use a version manager like
nvm.
Cause: Another process is already using port 3000.
Solution:
- Find the process:
lsof -i :3000 - Kill it:
kill -9 <PID> - Or change the port in your app:
app.listen(3001)
Cause: Incorrect import or instantiation.
Solution: Ensure you are importing the default export and instantiating it.
import App from 'newgatejs';
const app = new App(); // CorrectCause: Passing a non-function to a route method.
Solution: Check your route definitions.
// Incorrect
app.get('/', 'hello');
// Correct
app.get('/', (req, res) => res.send('hello'));} catch (err) { res.status(400).error({ message: 'YAML parsing failed', code: 400, details: { error: err.message } }); } });
### File Upload Size Exceeded
**Problem**: `File size exceeds limit`
**Causes**:
- File larger than configured limit
- Multiple files exceeding total memory limit
**Solution**:
```javascript
// Increase limits if needed
const parseFormData = require('newgatejs/src/parsers/formdata.js');
app.post('/upload', (req, res) => {
try {
const data = parseFormData(req, {
fileSizeLimit: 50 * 1024 * 1024, // 50MB per file
memoryLimit: 200 * 1024 * 1024, // 200MB total
fileCountLimit: 20 // 20 files max
});
res.json({ success: true });
} catch (err) {
res.status(413).error({
message: 'File too large',
code: 413,
details: { error: err.message }
});
}
});
Problem: Getting 404 for a route that should exist
Causes:
- Route registered after request
- Incorrect path pattern
- Method mismatch (GET vs POST)
Solution:
// Register routes before starting server
const app = new App();
// Register all routes FIRST
app.get('/users', (req, res) => res.json([]));
app.get('/users/:id', (req, res) => res.json({ id: req.params.id }));
// THEN start server
app.listen(3000);
// Debug: Log all registered routes
app.router.routes.forEach(route => {
console.log(`${route.method} ${route.path}`);
});Problem: req.params is empty or undefined
Causes:
- Parameter name mismatch
- Route pattern incorrect
Solution:
// Correct: Parameter name matches route
app.get('/users/:userId', (req, res) => {
console.log(req.params.userId); // Works
res.json({ id: req.params.userId });
});
// Wrong: Parameter name doesn't match
app.get('/users/:id', (req, res) => {
console.log(req.params.userId); // undefined
});Problem: req.query is empty
Causes:
- No query string in URL
- Incorrect URL format
Solution:
// Correct URL format
app.get('/search', (req, res) => {
console.log(req.query); // { q: 'test', limit: '10' }
res.json(req.query);
});
// Usage: GET /search?q=test&limit=10Problem: Wildcard route matches unintended paths
Causes:
- Wildcard route registered before specific routes
- Incorrect route ordering
Solution:
// Register specific routes BEFORE wildcard routes
app.get('/files/special', (req, res) => {
res.json({ special: true });
});
// Wildcard route AFTER specific routes
app.get('/files/*', (req, res) => {
res.json({ path: req.url });
});
// Now /files/special matches first route
// And /files/other matches wildcard routeProblem: Middleware code never runs
Causes:
next()not called in previous middleware- Route handler sends response before middleware
- Middleware registered after route
Solution:
// Register middleware BEFORE routes
app.use((req, res, next) => {
console.log('This runs first');
next(); // MUST call next()
});
// THEN register routes
app.get('/', (req, res) => {
res.json({ ok: true });
});
// NOT this order:
app.get('/', (req, res) => res.json({}));
app.use((req, res, next) => {}); // Won't run for existing routesProblem: Route executes before async middleware completes
Causes:
- Not awaiting async operation
- Not returning promise
Solution:
// Correct: Return promise or use async/await
app.use(async (req, res, next) => {
await database.connect();
next();
});
// Also correct:
app.use((req, res, next) => {
return database.connect().then(() => next());
});
// Wrong: Not returning promise
app.use((req, res, next) => {
database.connect(); // Fire and forget
next(); // Runs immediately
});Problem: Error handler doesn't execute
Causes:
- Error handler registered before routes
- Error not passed to
next() - Response already sent
Solution:
// Register routes FIRST
app.get('/data', (req, res, next) => {
try {
const data = JSON.parse(req.body);
res.json(data);
} catch (err) {
next(err); // Pass error to next middleware
}
});
// Error handler LAST
app.useError((err, req, res, next) => {
res.status(500).error({
message: err.message,
code: 500
});
});Problem: Error: Can't set headers after they are sent to the client
Causes:
- Calling
res.json()orres.send()twice - Setting headers after response sent
Solution:
// Wrong: Multiple responses
app.get('/', (req, res) => {
res.json({ ok: true });
res.json({ ok: false }); // Error!
});
// Correct: Single response
app.get('/', (req, res) => {
if (someCondition) {
res.json({ ok: true });
} else {
res.json({ ok: false });
}
});
// Also correct: Use return to exit early
app.get('/', (req, res) => {
if (someCondition) {
return res.json({ ok: true });
}
res.json({ ok: false });
});Problem: Response has wrong content type
Causes:
- Using wrong response method
- Not setting content type manually
Solution:
// Use correct response method
app.get('/json', (req, res) => {
res.json({ data: 'value' }); // Sets application/json
});
app.get('/csv', (req, res) => {
res.csv('a,b,c\n1,2,3'); // Sets text/csv
});
// Or set manually
app.get('/custom', (req, res) => {
res.set('Content-Type', 'application/custom');
res.send(data);
});Problem: File not downloading or corrupted
Causes:
- File path incorrect
- File doesn't exist
- Wrong MIME type
Solution:
import fs from 'fs';
import path from 'path';
app.get('/download/:filename', (req, res) => {
const filename = req.params.filename;
// Validate filename
if (filename.includes('..')) {
return res.status(400).error({
message: 'Invalid filename',
code: 400
});
}
const filepath = path.join('/safe/directory', filename);
// Check if file exists
if (!fs.existsSync(filepath)) {
return res.status(404).error({
message: 'File not found',
code: 404
});
}
// Use download with correct MIME type
const mimeTypes = {
'.pdf': 'application/pdf',
'.zip': 'application/zip',
'.txt': 'text/plain'
};
const ext = path.extname(filename);
const mimetype = mimeTypes[ext] || 'application/octet-stream';
res.download(filepath, filename);
});Problem: Requests taking too long
Causes:
- Synchronous operations in middleware
- Large file uploads
- Inefficient parsing
Solution:
// Use async operations
app.use(async (req, res, next) => {
// Good: Async database query
const user = await database.findUser(req.userId);
req.user = user;
next();
});
// Bad: Synchronous blocking operation
app.use((req, res, next) => {
const user = database.findUserSync(req.userId); // Blocks!
req.user = user;
next();
});
// Stream large files instead of buffering
app.get('/large-file', (req, res) => {
const stream = fs.createReadStream('/path/to/large/file');
res.stream(stream); // Good
// Not this:
const buffer = fs.readFileSync('/path/to/large/file');
res.send(buffer); // Bad - loads entire file in memory
});Problem: Memory usage grows over time
Causes:
- Large file uploads not cleaned up
- Memory leaks in middleware
- Unbounded caches
Solution:
// Limit file upload sizes
app.post('/upload', (req, res) => {
const options = {
fileSizeLimit: 10 * 1024 * 1024, // 10MB
memoryLimit: 50 * 1024 * 1024, // 50MB
fileCountLimit: 5
};
// Use options when parsing
});
// Clean up resources
app.onShutdown(async () => {
// Close database connections
await database.close();
// Clean up temporary files
fs.rmSync('/tmp/uploads', { recursive: true });
});
// Use bounded caches
const cache = new Map();
const MAX_CACHE_SIZE = 1000;
function cacheSet(key, value) {
if (cache.size >= MAX_CACHE_SIZE) {
const firstKey = cache.keys().next().value;
cache.delete(firstKey);
}
cache.set(key, value);
}Solution:
npm install newgatejsProblem: Another process using the port
Solution:
# Find process using port 3000
lsof -i :3000
# Kill process
kill -9 <PID>
# Or use different port
app.listen(3001);Problem: No permission to access file
Solution:
# Fix file permissions
chmod 644 /path/to/file
# Or run with appropriate permissions
sudo node app.jsProblem: File or directory doesn't exist
Solution:
import fs from 'fs';
import path from 'path';
// Check if file exists before accessing
if (!fs.existsSync(filepath)) {
return res.status(404).error({
message: 'File not found',
code: 404
});
}
// Create directory if needed
const dir = path.dirname(filepath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}If you encounter issues not covered here:
- Check the API Documentation
- Review Architecture Overview
- Check Security Practices
- Open an issue on GitHub
- Check existing issues for similar problems
// Log all requests
app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
console.log('Headers:', req.headers);
console.log('Body:', req.body);
next();
});
// Log all responses
app.use((req, res, next) => {
const originalEnd = res.end;
res.end = function(...args) {
console.log('Response Status:', res.statusCode);
console.log('Response Headers:', res.getHeaders());
originalEnd.apply(res, args);
};
next();
});node --inspect app.jsThen open chrome://inspect in Chrome DevTools.
import crypto from 'crypto';
app.use((req, res, next) => {
req.id = crypto.randomUUID();
res.set('X-Request-ID', req.id);
console.log(`[${req.id}] ${req.method} ${req.url}`);
next();
});