Loading...
Loading...
Analyze code for logic bugs, error handling issues, and edge cases. Detects off-by-one errors, null handling, race conditions, and incorrect error paths. Use when reviewing core business logic or complex algorithms.
npx skill4agent add xinbenlv/codereview-skills codereview-correctness// 🚨 Off-by-one
for (let i = 0; i <= arr.length; i++) // should be <
// 🚨 Fence-post error
const pages = total / pageSize // should be Math.ceil()// 🚨 Wrong operator
if (status = "active") // should be ===
// 🚨 Inverted logic
if (!isValid || !isEnabled) // should this be &&?// 🚨 Potential null dereference
const name = user.profile.name // user or profile could be null
// ✅ Safe access
const name = user?.profile?.name ?? 'Unknown'// 🚨 String + number = string
const result = "5" + 3 // "53" not 8
// 🚨 Truthy/falsy confusion
if (count) // 0 is falsy but may be valid// 🚨 Race condition
if (await fileExists(path)) {
await readFile(path) // file might be deleted between check and read
}// 🚨 No ordering guarantee
users.forEach(async user => await process(user))
// The loop completes before any process() finishes// 🚨 Race on shared state
if (!cache[key]) {
cache[key] = await expensiveCompute() // multiple calls may compute
}// 🚨 Error swallowed
try { riskyOperation() }
catch (e) { console.log(e) } // then what?
// ✅ Proper handling
try { riskyOperation() }
catch (e) {
logger.error('Operation failed', { error: e })
throw new OperationError('Failed', { cause: e })
}// 🚨 Catches everything including programming errors
try { ... }
catch (e) { return defaultValue } // hides bugs
// ✅ Specific error handling
catch (e) {
if (e instanceof NotFoundError) return defaultValue
throw e // rethrow unexpected errors
}// 🚨 Connection leak on error
const conn = await getConnection()
await query(conn) // if this throws, conn is never released
// ✅ Always cleanup
try { await query(conn) }
finally { conn.release() }// 🚨 Error lost
promise.then(handleSuccess) // no .catch()
// 🚨 Error in event handler
emitter.on('data', async (d) => await process(d)) // unhandled rejection[]""nullundefined// 🚨 Crashes on empty array
const first = items[0].name
// ✅ Handles empty
const first = items[0]?.name ?? 'default'// 🚨 No type validation
function process(id) {
return id.toString() // fails if id is null
}// 🚨 Negative index
const item = arr[index] // what if index is -1?
// 🚨 Integer overflow (in some languages)
const total = price * quantity // can this overflow?// 🚨 Timezone-naive
const today = new Date().toISOString().split('T')[0]
// 🚨 Midnight crossing
if (startDate === endDate) // what about times?// 🚨 Locale-dependent
const lower = str.toLowerCase() // Turkish 'I' problem
parseFloat("1,234.56") // fails in European locales// 🚨 Floating point comparison
if (0.1 + 0.2 === 0.3) // false!
// 🚨 Currency calculation
const total = 19.99 * 100 // 1998.9999999999998{
"findings": [
{
"severity": "major",
"category": "correctness",
"type": "null-dereference",
"evidence": {
"file": "src/users.ts",
"line": 42,
"snippet": "const name = user.profile.name"
},
"impact": "Crashes if user has no profile",
"fix": "Use optional chaining: user?.profile?.name ?? 'Unknown'",
"test": "Test with user object that has null profile"
}
]
}□ Logic Bugs
□ Off-by-one errors?
□ Wrong conditions/operators?
□ Null/undefined handled?
□ Type coercion issues?
□ Race Conditions
□ TOCTOU vulnerabilities?
□ Ordering guaranteed?
□ Shared state protected?
□ Error Handling
□ Errors not swallowed?
□ Right errors caught?
□ Resources cleaned up?
□ Async errors propagated?
□ Edge Cases
□ Empty input handled?
□ Huge input considered?
□ Wrong types rejected?
□ Boundaries validated?
□ Production
□ Timezone aware?
□ Locale independent?
□ Float precision handled?
□ Idempotent operations?