agentsclimarketplace

Error handler advisor

Skill VRIL-LABS/skill-jam/skills/error-handler-advisor

Welcome to the skill-jam β˜„οΈπŸ€

Install
npx -y skills add VRIL-LABS/skill-jam --skill error-handler-advisor

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Reviews code paths and suggests robust error handling β€” retries, fallbacks, circuit breakers, and user-friendly messages. Invoke when asked to improve error handling, add retries, implement fallbacks, review exception handling, or make error messages more user-friendly.

SKILL.md

6.8 KB, as published. Nobody here has run it

Error Handler Advisor

Reviews application code paths for missing, incomplete, or fragile error handling and recommends robust patterns β€” retries with exponential backoff, fallbacks, circuit breakers, graceful degradation, and user-friendly error messages.

When to Use

  • User asks to "improve error handling" or "add retries"
  • Code has bare catch(e) {} blocks or re-throws without context
  • An API or service call has no fallback if it fails
  • User asks about circuit breakers, bulkheads, or graceful degradation
  • Production incidents are caused by unhandled errors or cascading failures
  • User wants to make error messages more informative without leaking internals

Process

  1. Audit existing error handling for these anti-patterns:

    • Silent swallowing: catch (e) {} or catch (e) { return null; } with no logging
    • Over-broad catch: catching Exception or Error when only specific errors should be caught
    • Re-throwing without context: throw e loses the stack trace; use throw new Error('context', { cause: e })
    • Missing finally: resources (DB connections, file handles) not released on error
    • Leaking internals: stack traces or internal paths returned to API clients
    • No timeout: external service calls with no timeout β€” can hang indefinitely
    • No retry: transient network errors not retried
    • No fallback: critical path fails completely when a non-critical dependency is unavailable
  2. Classify each error type that can occur:

    • Transient (retriable): network timeouts, rate limit (429), service unavailable (503)
    • Permanent (not retriable): bad request (400), not found (404), auth failure (401/403)
    • Unknown: unhandled/unexpected errors β€” log, alert, return generic 500
  3. Recommend retry patterns for transient errors:

    • Exponential backoff: start at 100ms, double each attempt, cap at 30s
    • Jitter: add random offset to prevent thundering herd
    • Max retries: 3–5 for most cases; specify retry budget
    • Only retry idempotent operations (GET, DELETE) or operations with idempotency keys
  4. Recommend circuit breaker for repeated downstream failures:

    • Closed β†’ Open after N consecutive failures (or failure rate > threshold)
    • Open β†’ reject calls immediately for a cooldown period (30s–60s)
    • Half-Open β†’ allow a probe request; if successful, close the circuit
  5. Recommend fallbacks for graceful degradation:

    • Return cached data when the live source fails
    • Return a default/empty state rather than an error when appropriate
    • Disable a non-critical feature rather than failing the entire request
  6. Standardize error responses:

    • API errors should return a consistent JSON structure
    • Include: status, code (machine-readable), message (human-readable), requestId (for support)
    • Never include stack traces in production API responses
  7. Ensure errors are observable:

    • Log at the appropriate level (WARN for handled/expected, ERROR for unexpected)
    • Include context: user ID, request ID, operation name, input parameters (sanitized)
    • Emit metrics/alerts for error rate thresholds

Output Format

For each issue found, provide:

### Issue: Silent Error Swallowing
**Location:** `src/services/emailService.ts:34`
**Severity:** High

**Current:**
```ts
try {
  await sendWelcomeEmail(user);
} catch (e) {
  // silently ignored
}

Problem: If email sending fails, the error is lost. The caller has no idea the email was never sent. This also makes debugging impossible.

Recommended Fix:

try {
  await sendWelcomeEmail(user);
} catch (e) {
  // Email is non-critical β€” log and continue, but don't fail registration
  logger.warn({ err: e, userId: user.id }, 'Welcome email failed β€” will not retry');
  metrics.increment('email.welcome.failed');
}

Issue: No Retry on Transient Failures

Location: src/clients/inventoryClient.ts:89

Recommended Pattern:

import { retry } from 'async-retry'; // or implement manually

const stock = await retry(
  async () => {
    const res = await fetch(`${INVENTORY_URL}/stock/${productId}`);
    if (res.status === 503) throw new Error('Service unavailable'); // retriable
    if (!res.ok) throw Object.assign(new Error('Inventory error'), { bail: true }); // not retriable
    return res.json();
  },
  { retries: 3, factor: 2, minTimeout: 200, maxTimeout: 5000 }
);

## Examples

### Example Input
```python
def get_user_profile(user_id):
    response = requests.get(f"https://api.example.com/users/{user_id}")
    data = response.json()
    return data['profile']

Example Output

import time
import logging

logger = logging.getLogger(__name__)

def get_user_profile(user_id: str, max_retries: int = 3) -> dict:
    """Fetch user profile with retry on transient errors."""
    last_error = None
    for attempt in range(max_retries):
        try:
            response = requests.get(
                f"https://api.example.com/users/{user_id}",
                timeout=5  # always set a timeout
            )
            if response.status_code == 404:
                return None  # not found β€” don't retry
            response.raise_for_status()
            data = response.json()
            return data.get('profile')  # safe .get() instead of direct key access

        except (requests.Timeout, requests.ConnectionError) as e:
            last_error = e
            if attempt < max_retries - 1:
                backoff = 0.2 * (2 ** attempt)
                logger.warning("Retrying get_user_profile (attempt %d): %s", attempt + 1, e)
                time.sleep(backoff)

    logger.error("get_user_profile failed after %d attempts: %s", max_retries, last_error)
    raise RuntimeError(f"Could not fetch profile for user {user_id}") from last_error

Boundaries

  • Do NOT add retry logic to non-idempotent operations (POST, state-mutating calls) without adding idempotency keys.
  • Do NOT recommend catching BaseException / Throwable / panic unless there's a very specific reason.
  • Do NOT add circuit breakers to every call β€” reserve for high-volume calls to potentially unreliable dependencies.
  • Do NOT return raw exception messages to API clients β€” sanitize and log; return a generic message externally.
  • Do NOT add retries that could amplify load on an already-overloaded downstream service β€” always use backoff + jitter.
  • If the error handling strategy requires a specific library (e.g., resilience4j, tenacity, async-retry), check if it's already in the project's dependencies before recommending.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.