Errors
Error pattern analysis and troubleshooting for Claude Code sessions. Use when handling errors, fixing failures, troubleshooting issues.
Auto-activated — this skill loads automatically when Claude detects matching context.
Error Pattern Analysis
Analyze errors captured from Claude Code sessions to identify patterns and get actionable insights.
Quick Start
/errors # Batch analysis of historical error patterns
/debug # CC 2.1.30 real-time debug for current sessionWhen to Use Which
| Command | Purpose | Scope |
|---|---|---|
/errors | Batch analysis of error patterns (last 24h/7d) | Historical patterns |
/debug | Real-time debug of current session state | Current session |
/ork:fix-issue | Full RCA workflow for specific bug | Single issue |
Quick Analysis
# Run batch analysis on last 24h of errors
python .claude/scripts/analyze_errors.py
# Analyze last 7 days
python .claude/scripts/analyze_errors.py --days 7
# Generate markdown report
python .claude/scripts/analyze_errors.py --reportWhat Gets Captured
The error collector hook captures:
- Tool name (Bash, mcp__memory__search_nodes, etc.)
- Error message (first 500 chars)
- Tool input (command/query that failed)
- Timestamp and session ID
Location: .claude/logs/errors.jsonl
Current Error Rules
Check learned patterns that trigger warnings:
cat .claude/rules/error_rules.json | jq '.rules[] | {id, signature, count: .occurrence_count}'Files
| File | Purpose |
|---|---|
.claude/hooks/posttool/error-collector.sh | Captures errors to JSONL |
.claude/hooks/pretool/bash/error-pattern-warner.sh | Warns before risky commands |
.claude/scripts/analyze_errors.py | Batch pattern analysis |
.claude/rules/error_rules.json | Learned error patterns |
.claude/logs/errors.jsonl | Raw error log |
Common Patterns
Connection Refused / Wrong Port
pattern: ECONNREFUSED|connection refused|ERR_CONNECTION_REFUSED|connect ECONNREFUSED
fix: The port may have changed or the service isn't running.
1. Check services: portless list (if installed)
2. Use named URLs: api.localhost:1355 instead of localhost:PORT
3. Fallback: lsof -iTCP -sTCP:LISTEN -nP | grep -E 'node|python|java'
4. Install Portless to avoid port guessing: npm i -g portless
pattern: ERR_CONNECTION_RESET|ECONNRESET|socket hang up
fix: Service may have crashed. Check process logs, restart the service,
and use agent-browser to verify the app is responding:
agent-browser open "http://myapp.localhost:1355"PostgreSQL Connection Errors
pattern: role "X" does not exist
fix: Use Docker connection: docker exec -it orchestkit-postgres-dev psql -U orchestkit_user -d orchestkit_dev
pattern: relation "X" does not exist
fix: Check MCP postgres server connection string - may be connected to wrong databaseHook Errors (CC 2.1.98)
Since CC 2.1.98, hook errors show the first line of stderr directly in the transcript — no need for --debug:
pattern: hook.*error|hook.*failed|PreToolUse.*error
diagnosis: Read the stderr line shown in the transcript.
1. If path error → check CLAUDE_PLUGIN_ROOT is set
2. If JSON parse error → hook is returning invalid JSON
3. If timeout → hook exceeds 50ms budget (PreToolUse) or 100ms (PostToolUse)
4. If "module not found" → run: cd src/hooks && npm run buildRelated Skills
ork:fix-issue: Fix identified errorsdebug-investigator: Debug error root causes
Adding New Rules
Rules are auto-generated by analyze_errors.py when patterns repeat 2+ times.
For manual rules, edit .claude/rules/error_rules.json:
{
"id": "custom-001",
"pattern": "your regex pattern",
"signature": "human readable signature",
"tool": "Bash",
"occurrence_count": 1,
"fix_suggestion": "How to fix this"
}Rules (2)
Match error patterns precisely to avoid applying wrong fix templates to unrelated errors — HIGH
Match Error Patterns Precisely
Why
Error messages often share surface-level keywords. "connection refused" can mean a database is down, an API is unreachable, or a Docker network is misconfigured. Matching on keywords alone applies the wrong fix template, introducing new issues.
Rule
When matching errors to known patterns:
- Match the full error signature (tool + message + context), not just keywords
- Verify the tool name matches the expected source
- Check the input/command that triggered the error
- Confirm the fix template applies to this specific scenario
Incorrect — keyword-only matching
{
"rules": [
{
"pattern": "connection refused",
"fix_suggestion": "Start the PostgreSQL container"
}
]
}# Matches ANY "connection refused" error
def find_fix(error_message: str) -> str:
if "connection refused" in error_message:
return "Start the PostgreSQL container"
return "Unknown error"
# This will incorrectly tell users to start Postgres when:
# - Redis is down (port 6379)
# - An external API is unreachable (port 443)
# - MCP server failed to start (port 3100)Correct — match full error signature
{
"rules": [
{
"id": "pg-conn-001",
"pattern": "connection refused",
"tool": "Bash",
"input_pattern": "psql|pg_|postgres|5432",
"signature": "PostgreSQL connection refused",
"fix_suggestion": "Start PostgreSQL: docker compose up -d postgres"
},
{
"id": "redis-conn-001",
"pattern": "connection refused",
"tool": "Bash",
"input_pattern": "redis|6379",
"signature": "Redis connection refused",
"fix_suggestion": "Start Redis: docker compose up -d redis"
}
]
}import re
from dataclasses import dataclass
@dataclass
class ErrorRule:
id: str
pattern: str
tool: str
input_pattern: str
fix_suggestion: str
def find_fix(tool: str, error_message: str, tool_input: str, rules: list[ErrorRule]) -> ErrorRule | None:
for rule in rules:
if (rule.pattern in error_message
and rule.tool == tool
and re.search(rule.input_pattern, tool_input)):
return rule
return None # No match — do not guessMatching Precision Checklist
| Field | Required | Purpose |
|---|---|---|
| Error message pattern | Yes | What went wrong |
| Tool name | Yes | Where it happened |
| Input/command pattern | Yes | What triggered it |
| Occurrence count | Recommended | Confidence level |
| Last seen timestamp | Recommended | Staleness detection |
Common Ambiguous Patterns
| Keyword | Could Mean | Disambiguate By |
|---|---|---|
connection refused | DB, cache, API, MCP | Port number or tool |
not found | File, command, module, route | Error code (404 vs ENOENT) |
permission denied | File, network, auth | Path or HTTP status |
timeout | DB query, HTTP, DNS | Timeout duration and target |
Identify root cause before applying fixes to avoid masking real errors with suppressions — CRITICAL
Identify Root Cause Before Fixing
Why
The fastest "fix" for an error is to suppress it — wrap in try/catch, add || true, or swallow the exception. This hides the symptom while the underlying bug causes data corruption, silent failures, or cascading issues downstream.
Rule
Before applying any fix:
- Read the full error message and stack trace
- Identify the originating file and line number
- Trace the data flow to the root cause
- Fix the root cause, not the symptom
- Verify the error is resolved, not just silenced
Incorrect — suppress the error
// Error: Cannot read property 'name' of undefined
// "Fix": suppress it
try {
const name = user.profile.name;
} catch {
const name = "Unknown"; // Masks null user or missing profile
}# Error: connection refused on port 5432
# "Fix": ignore it
try:
db = connect("localhost:5432")
except Exception:
pass # Silently continues with no DB connection# Error: command not found
# "Fix": suppress with || true
some_missing_command || true
echo "Continuing..." # Proceeds without required stepProblems:
- The null user indicates an auth bypass or missing middleware
- The connection error means the DB is down or misconfigured
- The missing command means a dependency is not installed
Correct — trace to root cause then fix
// Error: Cannot read property 'name' of undefined
// Root cause: auth middleware not applied to this route
// Fix: add auth middleware, then safely access user
// 1. Add missing auth middleware
router.get("/profile", requireAuth, async (req, res) => {
// 2. User is now guaranteed by middleware
const user = req.user; // Non-null after requireAuth
res.json({ name: user.profile.name });
});# Error: connection refused on port 5432
# Root cause: DB container not started, or wrong port in config
# Fix: validate connection config, fail fast with actionable message
import os
db_url = os.environ.get("DATABASE_URL")
if not db_url:
raise RuntimeError(
"DATABASE_URL not set. Run: docker compose up -d postgres"
)
try:
db = connect(db_url)
except ConnectionRefusedError as e:
raise RuntimeError(
f"Cannot connect to database at {db_url}. "
"Is the postgres container running? Run: docker compose ps"
) from eRoot Cause Checklist
| Symptom | Likely Root Cause | Do NOT Do |
|---|---|---|
undefined is not an object | Missing null check or broken data flow | Wrap in try/catch |
connection refused | Service not running or wrong config | Add catch \{ pass \} |
command not found | Missing dependency | Add || true |
permission denied | Wrong user or file permissions | Run as root |
ENOSPC | Disk full | Delete random files |
Emulate Seed
Generate emulate seed configs for stateful API emulation. Wraps Vercel's emulate tool for GitHub, Vercel, Google OAuth, Slack, Apple Auth, Microsoft Entra, and AWS (S3/SQS/IAM) APIs. Not mocks — full state machines where create-a-PR-and-it-appears-in-the-list. Use when setting up test environments, CI pipelines, integration tests, or offline development.
Expect
Diff-aware AI browser testing — analyzes git changes, generates targeted test plans, and executes them via agent-browser. Reads git diff to determine what changed, maps changes to affected pages via route map, generates a test plan scoped to the diff, and runs it with pass/fail reporting. Use when testing UI changes, verifying PRs before merge, running regression checks on changed components, or validating that recent code changes don't break the user-facing experience.
Last updated on