Load PROACTIVELY when task involves investigating errors, diagnosing failures, or tracing unexpected behavior. Use when user says "debug this", "fix this error", "why is this failing", "trace this issue", or "it's not working". Covers error message and stack trace analysis, runtime debugging, network request inspection, state debugging, performance profiling, type error diagnosis, build failure resolution, and root cause analysis with memory-informed pattern matching against past failures.
Systematically diagnoses errors, traces root causes, and applies fixes using methodical debugging workflows.
/plugin marketplace add mgd34msu/goodvibes-plugin/plugin install goodvibes@goodvibes-marketThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/debugging-patterns.mdscripts/validate-debugging.shscripts/
validate-debugging.sh
references/
debugging-patterns.md
This skill teaches you how to debug systematically using GoodVibes precision tools. Effective debugging requires a methodical approach: reproduce the issue, isolate the cause, identify the root problem, apply a fix, and verify the solution.
Load this skill when:
Trigger phrases: "debug this error", "why is this failing", "investigate the issue", "trace the problem", "analyze the error".
Before debugging, confirm you can reproduce the issue reliably.
Collect all available error information.
precision_exec:
commands:
- cmd: "npm run typecheck 2>&1"
- cmd: "npm run lint 2>&1"
- cmd: "npm run build 2>&1"
verbosity: standard
What to capture:
Search for similar errors in the codebase.
discover:
queries:
- id: error_throw_sites
type: grep
pattern: "throw new (Error|TypeError|RangeError)"
glob: "**/*.{ts,tsx,js,jsx}"
- id: error_handlers
type: grep
pattern: "catch\\s*\\("
glob: "**/*.{ts,tsx,js,jsx}"
- id: console_errors
type: grep
pattern: "console\\.(error|warn)"
glob: "**/*.{ts,tsx,js,jsx}"
verbosity: locations
Pattern categories:
| Error Pattern | Meaning | Common Causes |
|---|---|---|
| ReferenceError | Variable not defined | Typo, missing import, scope issue |
| TypeError | Wrong type used | null/undefined, wrong method, type mismatch |
| RangeError | Value out of range | Array index, numeric overflow |
| SyntaxError | Invalid syntax | Parsing error, malformed JSON |
| NetworkError | Request failed | CORS, timeout, 404, auth failure |
Run the failing operation to confirm reproduction.
precision_exec:
commands:
- cmd: "npm run dev"
timeout_ms: 5000
verbosity: minimal
Reproduction checklist:
Reduce the problem space to find where the error originates.
Analyze the call stack to understand execution flow.
Stack trace example:
TypeError: Cannot read property 'name' of undefined
at getUserName (src/utils/user.ts:42:18)
at UserProfile (src/components/UserProfile.tsx:15:22)
at renderWithHooks (node_modules/react/cjs/react.development.js:1234)
Reading strategy:
precision_read:
files:
- path: "src/utils/user.ts"
extract: content
range: {start: 35, end: 50}
- path: "src/components/UserProfile.tsx"
extract: content
range: {start: 10, end: 25}
verbosity: standard
Follow the data from source to error point.
discover:
queries:
- id: function_calls
type: grep
pattern: "getUserName\\("
glob: "**/*.{ts,tsx}"
- id: data_sources
type: grep
pattern: "(fetch|axios|prisma).*user"
glob: "**/*.{ts,tsx}"
- id: prop_passing
type: grep
pattern: "user=\\{"
glob: "**/*.tsx"
verbosity: locations
Data flow analysis:
Test edge cases where errors commonly occur.
discover:
queries:
- id: array_access
type: grep
pattern: "\\[[0-9]+\\]|\\[.*\\]"
glob: "**/*.{ts,tsx}"
- id: null_checks
type: grep
pattern: "(if.*===.*null|if.*===.*undefined|\\?\\.|\\?\\?)"
glob: "**/*.{ts,tsx}"
- id: optional_chaining
type: grep
pattern: "\\?\\."
glob: "**/*.{ts,tsx}"
verbosity: locations
Common boundary issues:
| Issue | Example | Fix |
|---|---|---|
| Array out of bounds | arr[arr.length] | Check arr.length > 0 |
| Null/undefined access | user.name | Use user?.name |
| Division by zero | total / count | Check count !== 0 |
| Empty string operations | str[0] | Check str.length > 0 |
| Missing object keys | obj.key | Use obj?.key ?? default |
Determine the underlying problem, not just the symptom.
Classify the error to understand common causes.
Type Errors
precision_exec:
commands:
- cmd: "npm run typecheck 2>&1 | head -50"
verbosity: standard
Common TypeScript errors:
| Error Code | Meaning | Fix |
|---|---|---|
| TS2339 | Property does not exist | Add property to type or use optional chaining |
| TS2345 | Argument type mismatch | Fix the type or add type assertion |
| TS2322 | Type not assignable | Change the type or fix the value |
| TS2571 | Object is of type unknown | Add type guard or assertion |
| TS7006 | Implicit any parameter | Add parameter type annotation |
Runtime Errors
discover:
queries:
- id: unsafe_access
type: grep
pattern: "\\.[a-zA-Z]+(?!\\?)"
glob: "**/*.{ts,tsx}"
- id: async_errors
type: grep
pattern: "await.*(?!try)"
glob: "**/*.{ts,tsx}"
verbosity: files_only
Common runtime errors:
Module resolution errors are common.
discover:
queries:
- id: imports
type: grep
pattern: "^import.*from"
glob: "**/*.{ts,tsx}"
- id: dynamic_imports
type: grep
pattern: "import\\("
glob: "**/*.{ts,tsx}"
- id: require_statements
type: grep
pattern: "require\\("
glob: "**/*.{ts,js}"
verbosity: locations
Common import issues:
| Issue | Symptom | Fix |
|---|---|---|
| Missing export | Module has no exported member | Add export to source file |
| Circular dependency | Cannot access before initialization | Restructure imports |
| Wrong path | Module not found | Fix relative path or alias |
| Default vs named | X is not a function | Use import X or import { X } |
| Type-only import | Cannot use as value | Remove type keyword |
Question assumptions about data shape and state.
precision_grep:
queries:
- id: type_assertions
pattern: "as (unknown|any|[A-Z][a-zA-Z]+)"
glob: "**/*.{ts,tsx}"
output:
format: context
context_before: 2
context_after: 2
verbosity: standard
Dangerous assumptions:
Validate with:
if (typeof x === 'string'))if (x != null))x ?? defaultValue)Implement the fix based on root cause analysis.
Match the fix to the problem type.
Type Safety Fixes
// Before: Implicit any
function getUser(id) {
return users.find(u => u.id === id);
}
// After: Explicit types
function getUser(id: string): User | undefined {
return users.find(u => u.id === id);
}
Null Safety Fixes
// Before: Unsafe access
const name = user.profile.name;
// After: Optional chaining
const name = user?.profile?.name ?? 'Anonymous';
Async Error Handling
// Before: Unhandled promise
await fetchData();
// After: Try/catch
try {
await fetchData();
} catch (error: unknown) {
logger.error('Failed to fetch data', { error });
throw new AppError('Data fetch failed', { cause: error });
}
Array Boundary Fixes
// Before: Unsafe access
const first = items[0];
// After: Safe access
const first = items.length > 0 ? items[0] : null;
// Or: const first = items.at(0) ?? null;
Prevent similar errors in the future.
Input validation:
import { z } from 'zod';
const userSchema = z.object({
id: z.string().uuid(),
email: z.string().email(),
name: z.string().min(1).max(100),
});
function processUser(data: unknown) {
const user = userSchema.parse(data); // Throws if invalid
// Now user is type-safe
}
Type guards:
function isUser(value: unknown): value is User {
return (
typeof value === 'object' &&
value !== null &&
'id' in value &&
'email' in value
);
}
if (isUser(data)) {
// TypeScript knows data is User
logger.info('User email', { email: data.email });
}
Error boundaries (React):
import { ErrorBoundary } from 'react-error-boundary';
function ErrorFallback({ error }: { error: Error }) {
return (
<div role="alert">
<p>Something went wrong:</p>
<pre>{error.message}</pre>
</div>
);
}
<ErrorBoundary FallbackComponent={ErrorFallback}>
<MyComponent />
</ErrorBoundary>
Use precision_edit to make the change.
precision_edit:
edits:
- path: "src/utils/user.ts"
find: |
function getUserName(user) {
return user.name;
}
replace: |
function getUserName(user: User | undefined): string {
return user?.name ?? 'Unknown';
}
verbosity: minimal
Validate that the fix resolves the issue without breaking anything.
Ensure TypeScript errors are resolved.
precision_exec:
commands:
- cmd: "npm run typecheck"
verbosity: standard
All type errors must be resolved.
Confirm tests pass.
precision_exec:
commands:
- cmd: "npm test"
verbosity: standard
If tests fail:
Reproduce the original error scenario.
precision_exec:
commands:
- cmd: "npm run dev"
timeout_ms: 5000
verbosity: minimal
Verification checklist:
Debug API requests and responses.
Locate all HTTP requests.
discover:
queries:
- id: fetch_calls
type: grep
pattern: "fetch\\("
glob: "**/*.{ts,tsx,js,jsx}"
- id: axios_calls
type: grep
pattern: "axios\\.(get|post|put|delete|patch)"
glob: "**/*.{ts,tsx,js,jsx}"
- id: api_routes
type: glob
patterns: ["src/app/api/**/*.ts", "pages/api/**/*.ts"]
verbosity: locations
Validate error handling for network calls.
precision_grep:
queries:
- id: fetch_with_catch
pattern: "fetch\\([^)]+\\).*catch"
glob: "**/*.{ts,tsx,js,jsx}"
output:
format: context
context_after: 5
verbosity: standard
Common network issues:
| Issue | Symptom | Fix |
|---|---|---|
| CORS error | Blocked by CORS policy | Add CORS headers to API |
| 401 Unauthorized | Missing or invalid token | Add auth header, refresh token |
| 404 Not Found | Wrong URL or route | Fix endpoint path |
| 500 Server Error | Backend exception | Check server logs, fix backend |
| Timeout | Request takes too long | Increase timeout, optimize backend |
| Network failure | Failed to fetch | Check connectivity, retry logic |
Debugging CORS:
// Next.js API route
export async function GET(request: Request) {
return Response.json(data, {
headers: {
'Access-Control-Allow-Origin': '*', // Development only - use specific origin in production
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
},
});
}
Debugging authentication:
// Check for auth header
const token = request.headers.get('Authorization')?.replace('Bearer ', '');
if (!token) {
return Response.json({ error: 'Unauthorized' }, { status: 401 });
}
try {
const session = await verifyToken(token);
} catch (error: unknown) {
logger.error('Token verification failed', { error });
return Response.json({ error: 'Invalid token' }, { status: 401 });
}
Ensure request data is correct.
discover:
queries:
- id: request_bodies
type: grep
pattern: "(body:|JSON.stringify)"
glob: "**/*.{ts,tsx}"
- id: validation_schemas
type: grep
pattern: "z\\.object\\("
glob: "**/*.{ts,tsx}"
verbosity: locations
Request validation:
import { z } from 'zod';
const createUserSchema = z.object({
email: z.string().email(),
name: z.string().min(1).max(100),
});
export async function POST(request: Request) {
const body = await request.json();
const result = createUserSchema.safeParse(body);
if (!result.success) {
return Response.json(
{ error: 'Validation failed', details: result.error.flatten() },
{ status: 400 }
);
}
// Now result.data is type-safe
}
Debug React state and state management.
Locate state declarations and updates.
discover:
queries:
- id: useState_calls
type: grep
pattern: "useState<?"
glob: "**/*.{tsx,jsx}"
- id: state_updates
type: grep
pattern: "set[A-Z][a-zA-Z]*\\("
glob: "**/*.{tsx,jsx}"
- id: useEffect_hooks
type: grep
pattern: "useEffect\\("
glob: "**/*.{tsx,jsx}"
verbosity: locations
Common state issues:
| Issue | Symptom | Fix |
|---|---|---|
| Stale closure | State value is outdated | Use functional update |
| Missing dependency | useEffect doesn't re-run | Add to dependency array |
| Infinite loop | Component re-renders forever | Fix dependencies or condition |
| State race condition | Updates override each other | Use reducer or queue |
| Lost state on unmount | Data disappears | Lift state up or use global state |
Stale closure fix:
// Before: Stale closure
const [count, setCount] = useState(0);
function increment() {
setTimeout(() => {
setCount(count + 1); // count is stale
}, 1000);
}
// After: Functional update
function increment() {
setTimeout(() => {
setCount(prev => prev + 1); // Always current
}, 1000);
}
useEffect dependency fix:
// Before: Missing dependency
useEffect(() => {
fetchData(userId);
}, []); // userId changes ignored
// After: Complete dependencies
useEffect(() => {
fetchData(userId);
}, [userId]); // Re-runs when userId changes
Find direct state mutations (anti-pattern).
discover:
queries:
- id: array_mutations
type: grep
pattern: "\\.(push|pop|shift|unshift|splice)\\("
glob: "**/*.{tsx,jsx}"
- id: object_mutations
type: grep
pattern: "[a-zA-Z]+\\.[a-zA-Z]+\\s*=\\s*"
glob: "**/*.{tsx,jsx}"
verbosity: locations
Immutable updates:
// Before: Mutation
const [items, setItems] = useState([1, 2, 3]);
items.push(4); // BAD: Mutates state
setItems(items);
// After: Immutable
setItems([...items, 4]); // GOOD: New array
// Object updates
const [user, setUser] = useState({ name: 'Alice', age: 30 });
setUser({ ...user, age: 31 }); // GOOD: New object
Diagnose performance bottlenecks.
Search for common performance issues.
discover:
queries:
- id: n_plus_one
type: grep
pattern: "(for|forEach|map).*await.*(prisma|db|query)"
glob: "**/*.{ts,tsx}"
- id: inline_objects
type: grep
pattern: "(onClick|onChange|style)=\\{\\{"
glob: "**/*.{tsx,jsx}"
- id: missing_memo
type: grep
pattern: "(map|filter|reduce|sort)\\("
glob: "**/*.{tsx,jsx}"
verbosity: locations
Performance issues:
| Anti-pattern | Impact | Fix |
|---|---|---|
| N+1 queries | Slow database queries | Use include or batch loading |
| Inline objects in JSX | Unnecessary re-renders | Extract to constant or useMemo |
| Large lists without virtualization | Slow rendering | Use react-window or similar |
| Missing indexes | Slow queries | Add database indexes |
| Unnecessary re-renders | Laggy UI | Use React.memo, useMemo, useCallback |
Check for slow builds.
precision_exec:
commands:
- cmd: "npm run build"
verbosity: standard
Build performance issues:
Go beyond symptoms to find underlying issues.
Drill down to the root cause.
Example:
Root cause: Route parameter parsing doesn't handle edge cases.
Validate environment and dependencies.
precision_exec:
commands:
- cmd: "node --version"
- cmd: "npm --version"
- cmd: "npm list --depth=0"
verbosity: minimal
Common dependency issues:
Find what changed before the error appeared.
precision_exec:
commands:
- cmd: "git log --oneline -10"
- cmd: "git diff HEAD~5..HEAD"
verbosity: standard
Git bisect for complex issues:
git bisect start
git bisect bad HEAD
git bisect good v1.0.0
# Test, then mark:
git bisect good # or bad
# Repeat until culprit commit found
Add safeguards to prevent recurrence.
Write tests that catch the error.
import { describe, it, expect } from 'vitest';
describe('getUserName', () => {
it('should handle undefined user', () => {
expect(getUserName(undefined)).toBe('Unknown');
});
it('should handle user without name', () => {
expect(getUserName({ id: '123' })).toBe('Unknown');
});
it('should return user name', () => {
expect(getUserName({ id: '123', name: 'Alice' })).toBe('Alice');
});
});
Log key decision points for future debugging.
import { logger } from '@/lib/logger';
function processUser(user: User | undefined) {
if (!user) {
logger.warn('User is undefined in processUser');
return null;
}
logger.info('Processing user', { userId: user.id });
try {
// Process user
} catch (error: unknown) {
logger.error('Failed to process user', { userId: user.id, error });
throw error;
}
}
Logging best practices:
Track errors in production.
Error tracking (Sentry, Rollbar):
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 0.1,
beforeSend(event, hint) {
// Filter sensitive data
if (event.request) {
delete event.request.cookies;
}
return event;
},
});
Custom error classes:
export class AppError extends Error {
constructor(
message: string,
public code: string,
public statusCode: number = 500,
public context?: Record<string, unknown>
) {
super(message);
this.name = 'AppError';
}
}
throw new AppError('User not found', 'USER_NOT_FOUND', 404, { userId });
See references/debugging-patterns.md for detailed patterns organized by category.
Use discover to find multiple error patterns at once.
discover:
queries:
# Type safety issues
- { id: any_usage, type: grep, pattern: ':\\s*any', glob: '**/*.{ts,tsx}' }
- { id: type_assertions, type: grep, pattern: 'as (any|unknown)', glob: '**/*.{ts,tsx}' }
# Runtime safety
- { id: unsafe_access, type: grep, pattern: '\\.[a-zA-Z]+(?!\\?)', glob: '**/*.{ts,tsx}' }
- { id: unhandled_promises, type: grep, pattern: 'await.*(?!try)', glob: '**/*.{ts,tsx}' }
# Performance
- { id: n_plus_one, type: grep, pattern: 'for.*await.*prisma', glob: '**/*.{ts,tsx}' }
- { id: inline_objects, type: grep, pattern: 'onClick=\\{\\{', glob: '**/*.{tsx,jsx}' }
verbosity: locations
Step 1: Categorize the error
Step 2: Find similar patterns
Step 3: Trace the data
Step 4: Validate assumptions
Step 5: Fix and verify
Run parallel searches to find error patterns.
discover:
queries:
- id: error_sites
type: grep
pattern: "throw new"
glob: '**/*.{ts,tsx,js,jsx}'
- id: catch_blocks
type: grep
pattern: "catch\\s*\\("
glob: '**/*.{ts,tsx,js,jsx}'
- id: console_logs
type: grep
pattern: "console\\.(log|error|warn)"
glob: '**/*.{ts,tsx,js,jsx}'
verbosity: locations
Search with context for understanding surrounding code.
precision_grep:
queries:
- id: error_context
pattern: "TypeError|ReferenceError|RangeError"
glob: "**/*.{ts,tsx,js,jsx}"
output:
format: context
context_before: 5
context_after: 5
verbosity: standard
Run diagnostic commands.
precision_exec:
commands:
- cmd: "npm run typecheck 2>&1"
- cmd: "npm run lint 2>&1"
- cmd: "npm test 2>&1"
verbosity: standard
Apply fixes atomically.
precision_edit:
edits:
- path: "src/utils/user.ts"
find: "user.name"
replace: "user?.name ?? 'Unknown'"
verbosity: minimal
Use scripts/validate-debugging.sh to validate debugging practices.
./scripts/validate-debugging.sh /path/to/project
The script checks:
Reproduce:
Isolate:
Identify:
Fix:
Verify:
Prevent:
Critical (fix immediately):
High (fix soon):
Medium (fix when able):
Low (fix eventually):
Fixing symptoms, not causes:
Skipping verification:
Ignoring edge cases:
No prevention:
For complex issues, use binary search to narrow down.
Comment out half the code:
Explain the problem out loud:
Use git to find when the bug was introduced:
git bisect start
git bisect bad HEAD
git bisect good v1.0.0
# Test each commit
git bisect good # or bad
Trace important values:
function processData(data: unknown) {
logger.debug('Input data', { data });
const validated = schema.parse(data);
logger.debug('Validated data', { validated });
const transformed = transform(validated);
logger.debug('Transformed data', { transformed });
return transformed;
}
Use correlation IDs:
import { v4 as uuid } from 'uuid';
export async function POST(request: Request) {
const requestId = uuid();
logger.info('Request started', { requestId });
try {
const result = await processRequest(request);
logger.info('Request completed', { requestId });
return Response.json(result);
} catch (error: unknown) {
logger.error('Request failed', { requestId, error });
throw error;
}
}
references/debugging-patterns.md - Common error patterns by categoryscripts/validate-debugging.sh - Automated debugging practice validationActivates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.