Bug Fixing Examples¶
Overview¶
This guide demonstrates how to use Ralph Orchestrator for debugging and fixing code issues.
Example 1: Null Pointer Exception¶
Problem Code¶
def calculate_average(numbers):
total = sum(numbers)
return total / len(numbers)
# This crashes with: TypeError: unsupported operand type(s)
result = calculate_average(None)
Fix Request¶
prompt = """
Fix this function that crashes when passed None:
def calculate_average(numbers):
total = sum(numbers)
return total / len(numbers)
The function should handle None, empty lists, and non-numeric values gracefully.
"""
response = orchestrator.execute(prompt, agent="claude")
Fixed Code¶
def calculate_average(numbers):
"""
Calculate the average of a list of numbers.
Args:
numbers: List of numeric values or None
Returns:
float: Average value, or None if input is invalid
"""
# Handle None input
if numbers is None:
return None
# Handle empty list
if not numbers:
return 0
# Filter out non-numeric values
numeric_values = []
for num in numbers:
try:
numeric_values.append(float(num))
except (TypeError, ValueError):
continue
# Return None if no valid numbers found
if not numeric_values:
return None
return sum(numeric_values) / len(numeric_values)
Example 2: Memory Leak Fix¶
Problem Code¶
class EventManager {
constructor() {
this.events = {};
}
on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
}
emit(event, data) {
if (this.events[event]) {
this.events[event].forEach(cb => cb(data));
}
}
}
Fix Request¶
prompt = """
Fix the memory leak in this JavaScript EventManager class.
The class never removes event listeners, causing memory leaks.
Add an 'off' method and ensure proper cleanup.
"""
response = orchestrator.execute(prompt, agent="claude")
Fixed Code¶
class EventManager {
constructor() {
this.events = {};
this.eventIds = new WeakMap();
this.nextId = 0;
}
on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
// Store callback with unique ID for removal
const id = this.nextId++;
const callbackWrapper = { id, callback };
this.events[event].push(callbackWrapper);
this.eventIds.set(callback, id);
// Return unsubscribe function
return () => this.off(event, callback);
}
off(event, callback) {
if (!this.events[event]) return;
const id = this.eventIds.get(callback);
if (id !== undefined) {
this.events[event] = this.events[event].filter(
wrapper => wrapper.id !== id
);
this.eventIds.delete(callback);
// Clean up empty event arrays
if (this.events[event].length === 0) {
delete this.events[event];
}
}
}
emit(event, data) {
if (this.events[event]) {
this.events[event].forEach(wrapper =>
wrapper.callback(data)
);
}
}
// Clear all listeners for an event
removeAllListeners(event) {
if (event) {
delete this.events[event];
} else {
this.events = {};
}
}
// Cleanup method for destroying the instance
destroy() {
this.events = {};
this.eventIds = new WeakMap();
}
}
Example 3: Race Condition Fix¶
Problem Code¶
import threading
class Counter:
def __init__(self):
self.count = 0
def increment(self):
temp = self.count
# Simulating some processing
temp = temp + 1
self.count = temp
Fix Request¶
prompt = """
Fix the race condition in this Counter class that occurs when
multiple threads call increment() simultaneously.
"""
response = orchestrator.execute(prompt, agent="claude")
Fixed Code¶
import threading
from contextlib import contextmanager
class Counter:
def __init__(self):
self.count = 0
self._lock = threading.Lock()
def increment(self):
"""Thread-safe increment operation."""
with self._lock:
temp = self.count
# Simulating some processing
temp = temp + 1
self.count = temp
def decrement(self):
"""Thread-safe decrement operation."""
with self._lock:
self.count -= 1
def get_value(self):
"""Thread-safe read operation."""
with self._lock:
return self.count
@contextmanager
def batch_operation(self):
"""Context manager for batch operations."""
self._lock.acquire()
try:
yield self
finally:
self._lock.release()
# Usage example:
counter = Counter()
# Batch operations
with counter.batch_operation():
for _ in range(100):
counter.count += 1 # Direct access within context
Example 4: SQL Injection Vulnerability¶
Problem Code¶
Fix Request¶
prompt = """
Fix the SQL injection vulnerability in this function.
Use parameterized queries and add input validation.
"""
response = orchestrator.execute(prompt, agent="claude")
Fixed Code¶
def get_user(user_id):
"""
Safely retrieve user by ID with SQL injection protection.
Args:
user_id: User identifier (int or string)
Returns:
dict: User data or None if not found
Raises:
ValueError: If user_id is invalid
"""
# Input validation
if user_id is None:
raise ValueError("User ID cannot be None")
try:
# Convert to integer to ensure type safety
user_id = int(user_id)
except (ValueError, TypeError):
raise ValueError(f"Invalid user ID: {user_id}")
# Additional validation
if user_id <= 0:
raise ValueError("User ID must be positive")
# Use parameterized query to prevent SQL injection
query = "SELECT * FROM users WHERE id = %s"
try:
result = db.execute(query, (user_id,))
return result.fetchone()
except DatabaseError as e:
logger.error(f"Database error fetching user {user_id}: {e}")
return None
# Additional secure version using ORM
def get_user_orm(user_id):
"""ORM-based user retrieval (recommended)."""
try:
user_id = int(user_id)
return User.query.filter_by(id=user_id).first()
except (ValueError, TypeError):
return None
Example 5: Infinite Loop Fix¶
Problem Code¶
def find_target(arr, target):
left = 0
right = len(arr) - 1
while left < right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid # Bug: should be mid + 1
else:
right = mid
return -1
Fix Request¶
prompt = """
Fix the infinite loop bug in this binary search implementation.
The function gets stuck when the target is not in the array.
"""
response = orchestrator.execute(prompt, agent="claude")
Fixed Code¶
def find_target(arr, target):
"""
Binary search implementation with infinite loop fix.
Args:
arr: Sorted array to search
target: Value to find
Returns:
int: Index of target or -1 if not found
"""
if not arr:
return -1
left = 0
right = len(arr) - 1
while left <= right: # Changed condition to include equality
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1 # Fixed: increment to avoid infinite loop
else:
right = mid - 1 # Fixed: decrement for consistency
return -1
# Enhanced version with additional features
def find_target_enhanced(arr, target, return_insertion_point=False):
"""
Enhanced binary search with insertion point option.
Args:
arr: Sorted array to search
target: Value to find
return_insertion_point: If True, return where target should be inserted
Returns:
int: Index of target, or insertion point if not found and requested
"""
if not arr:
return 0 if return_insertion_point else -1
left = 0
right = len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return left if return_insertion_point else -1
Common Bug Patterns and Fixes¶
1. Off-by-One Errors¶
- Check array bounds
- Verify loop conditions
- Test edge cases (empty, single element)
2. Null/Undefined Handling¶
- Add null checks at function entry
- Use optional chaining in JavaScript
- Provide sensible defaults
3. Resource Leaks¶
- Implement proper cleanup (close files, connections)
- Use context managers in Python
- Add finally blocks for cleanup
4. Concurrency Issues¶
- Use locks for shared resources
- Implement atomic operations
- Consider using thread-safe data structures
5. Type Errors¶
- Add type checking/validation
- Use TypeScript/type hints
- Handle type conversions explicitly
Debugging Tips¶
- Reproduce First: Always reproduce the bug before fixing
- Add Logging: Insert strategic logging to understand flow
- Unit Tests: Write tests that expose the bug
- Edge Cases: Test with empty, null, and boundary values
- Code Review: Have the fix reviewed by others