Errors
Error pattern analysis and troubleshooting for Claude Code sessions. Categorizes errors (network, auth, model, tool, memory, permission) with known resolution patterns, searches memory for prior occurrences, and suggests recovery steps. Delegates to debug-investigator agent for complex root cause analysis. Use when handling errors, fixing failures, or troubleshooting session 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, AWS (S3/SQS/IAM), Okta, Clerk, Resend, Stripe, and MongoDB Atlas APIs. Not mocks — full state machines where create-a-PR-and-it-appears-in-the-list, send-an-email-and-retrieve-from-local-inbox. 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 (Rust daemon + CDP, ARIA-tree-first). 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