Skill: charlie-morrison/error-diagnosis (version 1.0.1)

# Error Diagnosis Analyze error messages, stack traces, and log output to diagnose root causes and suggest fixes. Use when debugging crashes, runtime errors, build failures, or unexpected behavior. ## Usage ``` Diagnose this error: [paste error message or stack trace] ``` Or with context: ``` Diagnose: [error]. Language: [lang]. Framework: [framework]. Recent changes: [what changed]. ``` ## How It Works 1. **Parse** — extract error type, message, file locations, line numbers from raw output 2. **Classify** — categorize the error (syntax, runtime, dependency, config, permission, network, OOM, etc.) 3. **Trace** — follow the call stack to identify the originating code vs. where the error surfaced 4. **Diagnose** — determine root cause using error patterns, common pitfalls, and framework-specific knowledge 5. **Fix** — provide actionable fix with code snippets ## Supported Error Sources - **Stack traces**: Python, JavaScript/Node.js, Java, Go, Rust, C/C++, Ruby, PHP - **Build errors**: npm, pip, cargo, gradle, maven, webpack, vite, tsc - **Runtime errors**: segfaults, OOM, deadlocks, race conditions, type errors - **Infrastructure**: Docker, Kubernetes, systemd, nginx, database connection errors - **CI/CD**: GitHub Actions, GitLab CI, CircleCI failure logs ## Output Format ```markdown ## Error Type [Classification: e.g., "TypeError — accessing property of undefined"] ## Root Cause [1-2 sentences explaining WHY this happened] ## Fix [Code snippet or command to resolve] ## Prevention [How to avoid this in the future: type check, test, lint rule, etc.] ``` ## Advanced Features ### Multi-Error Analysis Paste multiple errors — the skill identifies whether they share a root cause or are independent issues. ### Regression Detection ``` This error started after [commit/change]. Analyze whether the change could cause this. ``` ### Environment Comparison ``` Works in dev, fails in prod. Error: [error]. Dev config: [config]. Prod config: [config]. ``` ## Scripts ### `scripts/parse_stacktrace.py` Extracts structured data from raw stack traces: ```bash python3 scripts/parse_stacktrace.py < error.log ``` Returns JSON with error type, message, frames (file, line, function), and suggested search queries.

path: scripts/parse_stacktrace.py
content: #!/usr/bin/env python3
"""Parse stack traces from various languages into structured JSON."""

import sys
import re
import json

def parse_python(text):
    frames = []
    for m in re.finditer(r'File "([^"]+)", line (\d+), in (\w+)', text):
        frames.append({"file": m.group(1), "line": int(m.group(2)), "function": m.group(3)})
    err_match = re.search(r'^(\w+Error|\w+Exception|KeyboardInterrupt): (.+)$', text, re.MULTILINE)
    if not err_match:
        err_match = re.search(r'^(\w+Error|\w+Exception)$', text, re.MULTILINE)
    error_type = err_match.group(1) if err_match else "Unknown"
    error_msg = err_match.group(2) if err_match and err_match.lastindex >= 2 else ""
    return {"language": "python", "error_type": error_type, "message": error_msg, "frames": frames}

def parse_javascript(text):
    frames = []
    for m in re.finditer(r'at (?:(.+?) \()?(.+?):(\d+):(\d+)\)?', text):
        frames.append({
            "function": m.group(1) or "<anonymous>",
            "file": m.group(2), "line": int(m.group(3)), "column": int(m.group(4))
        })
    err_match = re.search(r'^(\w+Error|\w+Exception): (.+)$', text, re.MULTILINE)
    error_type = err_match.group(1) if err_match else "Unknown"
    error_msg = err_match.group(2) if err_match else ""
    return {"language": "javascript", "error_type": error_type, "message": error_msg, "frames": frames}

def parse_java(text):
    frames = []
    for m in re.finditer(r'at ([\w.$]+)\(([\w.]+):(\d+)\)', text):
        frames.append({"function": m.group(1), "file": m.group(2), "line": int(m.group(3))})
    err_match = re.search(r'^([\w.]+(?:Error|Exception)): (.+)$', text, re.MULTILINE)
    error_type = err_match.group(1) if err_match else "Unknown"
    error_msg = err_match.group(2) if err_match else ""
    return {"language": "java", "error_type": error_type, "message": error_msg, "frames": frames}

def parse_go(text):
    frames = []
    for m in re.finditer(r'([\w/.-]+\.go):(\d+)', text):
        frames.append({"file": m.group(1), "line": int(m.group(2))})
    err_match = re.search(r'(?:panic|fatal error): (.+)', text)
    error_type = "panic" if "panic:" in text else "fatal error" if "fatal error:" in text else "error"
    error_msg = err_match.group(1) if err_match else ""
    return {"language": "go", "error_type": error_type, "message": error_msg, "frames": frames}

def detect_and_parse(text):
    if re.search(r'File ".*", line \d+', text):
        return parse_python(text)
    if re.search(r'at .+:\d+:\d+', text):
        return parse_javascript(text)
    if re.search(r'at [\w.$]+\([\w.]+:\d+\)', text):
        return parse_java(text)
    if re.search(r'\.go:\d+', text):
        return parse_go(text)
    err_match = re.search(r'(?:error|Error|ERROR)[:\s]+(.+)', text)
    return {
        "language": "unknown",
        "error_type": "Error",
        "message": err_match.group(1).strip() if err_match else text.strip()[:200],
        "frames": []
    }

if __name__ == "__main__":
    text = sys.stdin.read()
    result = detect_and_parse(text)
    result["search_queries"] = [
        f'{result["language"]} {result["error_type"]} {result["message"][:80]}',
        f'{result["error_type"]} {result["message"][:50]} fix',
    ]
    print(json.dumps(result, indent=2))


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)