---
title: "Errors"
description: "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."
---

<span className="badge badge-gray">Reference</span> <span className="badge badge-green">low</span>

> **Auto-activated** — this skill loads automatically when Claude detects matching context.

<ContextualSkillSidebar slug="errors" />


# Error Pattern Analysis

Analyze errors captured from Claude Code sessions to identify patterns and get actionable insights.

## Quick Start

```bash
/errors              # Batch analysis of historical error patterns
/debug               # CC 2.1.30 real-time debug for current session
```

### When 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

```bash
# 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:

```bash
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 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
```

## Related Skills
- `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`:

```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

```json
{
  "rules": [
    {
      "pattern": "connection refused",
      "fix_suggestion": "Start the PostgreSQL container"
    }
  ]
}
```

```python
# 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

```json
{
  "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"
    }
  ]
}
```

```python
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

| 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:
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

```typescript
// 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
}
```

```python
# Error: connection refused on port 5432
# "Fix": ignore it
try:
    db = connect("localhost:5432")
except Exception:
    pass  # Silently continues with no DB connection
```

```bash
# 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

```typescript
// 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 });
});
```

```python
# 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

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

