About 80% of production bugs fall into a handful of recognizable categories. Not exotic failures from rare edge cases, not subtle logic errors that require deep domain expertise. Just the same mechanical mistakes, repeated across thousands of codebases.
Null references. Unhandled promises. Type mismatches. Missing error boundaries.
These errors plague production systems not because developers are careless, but because writing error-free code at scale is genuinely difficult. You're building systems that handle millions of requests, integrating with dozens of services, managing async operations across distributed networks. Mistakes happen.
This is exactly what autonomous code repair is designed to handle: the common, mechanical errors that machines can recognize and fix reliably. Here are the top 7 categories with real examples, and how bugstack.ai approaches each one.
1. Null or Undefined Reference Errors (30-40% of production bugs)
This is the #1 cause of production failures. JavaScript calls .split() on undefined. Python tries to access a dict key that doesn't exist. Go receives a nil pointer. Same category of failure, different syntax.
Example: JavaScript
// Production error: Cannot read property 'email' of undefined
function sendWelcomeEmail(user) {
const email = user.email.toLowerCase(); // Crashes if user is null/undefined
sendEmail(email, welcomeTemplate);
}
What causes it:
- API returns
nullinstead of expected object - Async operation completes but doesn't set expected data
- Third-party service returns different schema than expected
- Default parameter not provided
How bugstack.ai fixes it:
The system recognizes that user could be null and generates a safe alternative:
function sendWelcomeEmail(user) {
if (!user || !user.email) {
console.warn('User or email is missing, skipping welcome email');
return;
}
const email = user.email.toLowerCase();
sendEmail(email, welcomeTemplate);
}
Or, using optional chaining:
function sendWelcomeEmail(user) {
const email = user?.email?.toLowerCase();
if (!email) {
console.warn('Email missing, skipping welcome email');
return;
}
sendEmail(email, welcomeTemplate);
}
Python equivalent:
# Before: KeyError if email not in user dict
def send_welcome_email(user):
email = user['email'].lower()
send_email(email, welcome_template)
# After: Safe with fallback
def send_welcome_email(user):
if not user or 'email' not in user:
logger.warning('User or email missing')
return
email = user['email'].lower()
send_email(email, welcome_template)
2. Unhandled Promise Rejections (Node.js, async JavaScript)
Node.js has a quirk: if a promise rejects and there's no .catch() handler, the entire process can crash or silently fail, becoming a ghost error.
Example:
// No catch handler: if the promise rejects, it's silently lost
async function fetchUserData(userId) {
const response = await fetch(`/api/users/${userId}`);
const user = await response.json();
return user;
}
// Called somewhere, but nobody is waiting for the promise
fetchUserData(123); // Fire and forget = disaster
What causes it:
- Missing
.catch()ortry/catchblock - Fire-and-forget async operations
- Promise chains that don't end with error handling
- Third-party SDK that rejects but you're not prepared for it
How bugstack.ai fixes it:
async function fetchUserData(userId) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error(`API returned ${response.status}: ${response.statusText}`);
}
const user = await response.json();
return user;
} catch (error) {
logger.error('Failed to fetch user data', { userId, error: error.message });
return null;
}
}
void fetchUserData(123).catch(error => {
logger.error('Unexpected error in fetchUserData', error);
});
3. Type Mismatches and Schema Violations
You expect a string, you get a number. You expect an object, you get an array. TypeScript helps prevent this at compile time, but JavaScript and Python still suffer from it in production.
Example: JavaScript
// API returns user.age as a string "25", not a number
function canVoteInUS(user) {
return user.age >= 18; // Comparing string "25" >= 18 works, but conceptually wrong
}
function applyAgeDiscount(user) {
const discountedPrice = basePrice * (1 - user.age / 100); // NaN if age is "25" string
return discountedPrice;
}
How bugstack.ai fixes it:
function canVoteInUS(user) {
const age = parseInt(user.age, 10);
if (isNaN(age)) {
throw new Error(`Invalid age format: ${user.age}`);
}
return age >= 18;
}
function applyAgeDiscount(user) {
const age = Number(user.age);
if (isNaN(age) || age < 0 || age > 150) {
throw new Error(`Age out of valid range: ${user.age}`);
}
const discountedPrice = basePrice * (1 - age / 100);
return discountedPrice;
}
4. Resource Leaks (Connections, File Handles, Memory)
Your code opens a database connection, a file, or a websocket, but doesn't close it. Over time, your application runs out of resources and crashes.
Example: JavaScript (Database)
// Connection is never closed
async function getUserById(id) {
const connection = await pool.getConnection();
const user = await connection.query(`SELECT * FROM users WHERE id = ?`, [id]);
return user[0];
// connection is never released!
}
How bugstack.ai fixes it:
async function getUserById(id) {
const connection = await pool.getConnection();
try {
const result = await connection.query(`SELECT * FROM users WHERE id = ?`, [id]);
return result[0];
} finally {
await connection.release();
}
}
Python:
# Before
def read_config():
f = open('config.json')
config = json.load(f)
return config
# After: context manager
def read_config():
with open('config.json') as f:
config = json.load(f)
return config
5. Missing Error Handlers for Async Operations
You start an async operation but don't handle what happens if it fails. The operation hangs, times out, or fails silently.
Example:
app.post('/send-email', (req, res) => {
sendEmailAsync(req.body.email).then(
() => console.log('Email sent')
);
// No .catch() handler!
res.json({ status: 'ok' });
});
How bugstack.ai fixes it:
app.post('/send-email', async (req, res) => {
try {
await sendEmailAsync(req.body.email);
res.json({ status: 'ok', message: 'Email sent successfully' });
} catch (error) {
logger.error('Failed to send email', { email: req.body.email, error });
res.status(500).json({
status: 'error',
message: 'Failed to send email. Please try again.'
});
}
});
6. Configuration and Environment Variable Errors
Your application depends on environment variables. At deployment, a variable is missing or misspelled, and your application crashes.
Example:
const dbUrl = process.env.DATABASE_URL;
const pool = new Pool({ connectionString: dbUrl });
// If DATABASE_URL is not set, pool is created with undefined, crashes at runtime
How bugstack.ai fixes it:
function validateConfig() {
const required = ['DATABASE_URL', 'API_KEY', 'LOG_LEVEL'];
const missing = required.filter(key => !process.env[key]);
if (missing.length > 0) {
throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
}
}
validateConfig();
const dbUrl = process.env.DATABASE_URL;
const pool = new Pool({ connectionString: dbUrl });
7. Off-by-One Errors and Array Index Issues
Subtle logic errors that cause you to access the wrong element, skip an element, or go out of bounds.
Example:
function getFirstNItems(array, n) {
const result = [];
for (let i = 1; i <= n; i++) { // Should start at 0, not 1
result.push(array[i]);
}
return result;
}
How bugstack.ai fixes it:
function getFirstNItems(array, n) {
const result = [];
const limit = Math.min(n, array.length);
for (let i = 0; i < limit; i++) {
result.push(array[i]);
}
return result;
}
Why These Patterns Matter
These seven categories account for the vast majority of production failures. They share a few important traits:
They're mechanical, not logical. A null check isn't a business decision. An unhandled promise isn't a design flaw. These are patterns that follow clear rules and can be fixed consistently.
They're high-frequency. Any codebase processing real traffic will encounter these errors regularly. Each individual occurrence is minor, but collectively they consume enormous engineering time.
They're perfect for automation. Because these errors follow recognizable patterns, AI can detect them, generate fixes, and validate those fixes with high confidence. This is the sweet spot for autonomous code repair.
The complex bugs, the ones requiring deep domain knowledge or architectural changes, still need human engineers. But the mechanical errors that fill your error logs and burn your on-call engineers' time? Those can be handled automatically, 24/7, without pulling anyone off feature work.
bugstack.ai monitors your production errors and delivers validated fixes as pull requests. The common bugs described above are exactly what it's built to handle. Start a free 14-day trial at bugstack.ai.