Skip to main content
OrchestKit v7.43.0 — 104 skills, 36 agents, 173 hooks · Claude Code 2.1.105+
OrchestKit
Skills

Errors

Error pattern analysis and troubleshooting for Claude Code sessions. Use when handling errors, fixing failures, troubleshooting issues.

Reference low

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 session

When to Use Which

CommandPurposeScope
/errorsBatch analysis of error patterns (last 24h/7d)Historical patterns
/debugReal-time debug of current session stateCurrent session
/ork:fix-issueFull RCA workflow for specific bugSingle 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 --report

What 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

FilePurpose
.claude/hooks/posttool/error-collector.shCaptures errors to JSONL
.claude/hooks/pretool/bash/error-pattern-warner.shWarns before risky commands
.claude/scripts/analyze_errors.pyBatch pattern analysis
.claude/rules/error_rules.jsonLearned error patterns
.claude/logs/errors.jsonlRaw 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 database

Hook 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 build
  • ork:fix-issue: Fix identified errors
  • debug-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:

  1. Match the full error signature (tool + message + context), not just keywords
  2. Verify the tool name matches the expected source
  3. Check the input/command that triggered the error
  4. 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 guess

Matching Precision Checklist

FieldRequiredPurpose
Error message patternYesWhat went wrong
Tool nameYesWhere it happened
Input/command patternYesWhat triggered it
Occurrence countRecommendedConfidence level
Last seen timestampRecommendedStaleness detection

Common Ambiguous Patterns

KeywordCould MeanDisambiguate By
connection refusedDB, cache, API, MCPPort number or tool
not foundFile, command, module, routeError code (404 vs ENOENT)
permission deniedFile, network, authPath or HTTP status
timeoutDB query, HTTP, DNSTimeout 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:

  1. Read the full error message and stack trace
  2. Identify the originating file and line number
  3. Trace the data flow to the root cause
  4. Fix the root cause, not the symptom
  5. 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 step

Problems:

  • 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 e

Root Cause Checklist

SymptomLikely Root CauseDo NOT Do
undefined is not an objectMissing null check or broken data flowWrap in try/catch
connection refusedService not running or wrong configAdd catch \{ pass \}
command not foundMissing dependencyAdd || true
permission deniedWrong user or file permissionsRun as root
ENOSPCDisk fullDelete random files
Edit on GitHub

Last updated on