Skip to content
Back to skills

Structured Errors Ricardoroche Ricardos Claude Code 2

ASecurity

Automatically applies when writing error handling in APIs and tools. Ensures errors are returned as structured JSON with error, request_id, and timestamp (not plain strings).

  • 666 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 2, 2026
ai-agentspythonsqlfastapidebuggingapidatabasesecurity

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 2, 2026

npx -y skills add majiayu000/claude-skill-registry --skill structured-errors-ricardoroche-ricardos-claude-code-2 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Structured Errors Ricardoroche Ricardos Claude Code 2?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Structured Errors Ricardoroche Ricardos Claude Code 2
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/majiayu000-structured-errors-ricardoroche-ricardos-claude-cod/badge)](https://www.skillsdirectory.com/skills/majiayu000-structured-errors-ricardoroche-ricardos-claude-cod)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: structured-errors
description: Automatically applies when writing error handling in APIs and tools. Ensures errors are returned as structured JSON with error, request_id, and timestamp (not plain strings).
---

# Structured Error Response Enforcer

When writing error handling in API endpoints, tools, or services, always return structured JSON errors.

## ✅ Correct Pattern

```python
import uuid
from datetime import datetime
import json

def create_error_response(
    error_message: str,
    status_code: int = 500,
    details: dict = None
) -> dict:
    """Create structured error response."""
    response = {
        "error": error_message,
        "request_id": str(uuid.uuid4()),
        "timestamp": datetime.now().isoformat(),
        "status_code": status_code
    }
    if details:
        response["details"] = details
    return response

# In API endpoint
@app.get("/users/{user_id}")
async def get_user(user_id: str):
    if not user_id:
        raise HTTPException(
            status_code=400,
            detail=create_error_response(
                "User ID is required",
                status_code=400
            )
        )

    try:
        user = await fetch_user(user_id)
        return user
    except UserNotFoundError:
        raise HTTPException(
            status_code=404,
            detail=create_error_response(
                "User not found",
                status_code=404,
                details={"user_id": user_id}
            )
        )

# In tool function
def process_data(data: str) -> str:
    if not data:
        return json.dumps(create_error_response(
            "Data is required",
            status_code=400
        ))

    try:
        result = parse_data(data)
        return json.dumps({"result": result})
    except Exception as e:
        return json.dumps(create_error_response(
            "Failed to process data",
            status_code=500,
            details={"error_type": type(e).__name__}
        ))
```

## ❌ Incorrect Pattern

```python
# ❌ Plain string
if not user_id:
    return "Error: user ID is required"

# ❌ Exposing sensitive data
except httpx.HTTPStatusError as e:
    return f"Error: {e.response.text}"  # ❌ Leaks API response

# ❌ No request ID for tracing
return {"error": "Something went wrong"}

# ❌ Inconsistent error format
return "Error: failed"  # Sometimes string
return {"message": "failed"}  # Sometimes object
```

## Required Fields

**All error responses must include:**
1. **error** (string) - Human-readable error message
2. **request_id** (uuid) - For tracing/debugging
3. **timestamp** (ISO string) - When error occurred
4. **status_code** (int) - HTTP status code

**Optional but recommended:**
5. **details** (object) - Additional context (safe data only)
6. **error_code** (string) - Application-specific error code
7. **field** (string) - Which field caused the error (validation)

## Custom Exception Classes

```python
class APIError(Exception):
    """Base exception for API errors."""

    def __init__(self, message: str, status_code: int = 500, details: dict = None):
        self.message = message
        self.status_code = status_code
        self.details = details or {}
        self.request_id = str(uuid.uuid4())
        self.timestamp = datetime.now().isoformat()
        super().__init__(self.message)

    def to_dict(self) -> dict:
        """Convert to structured error response."""
        return {
            "error": self.message,
            "status_code": self.status_code,
            "request_id": self.request_id,
            "timestamp": self.timestamp,
            "details": self.details
        }

class ValidationError(APIError):
    """Validation error."""
    def __init__(self, message: str, field: str = None):
        details = {"field": field} if field else {}
        super().__init__(message, status_code=400, details=details)

class NotFoundError(APIError):
    """Resource not found."""
    def __init__(self, resource: str, resource_id: str):
        super().__init__(
            f"{resource} not found",
            status_code=404,
            details={"resource": resource, "id": resource_id}
        )

# Usage
try:
    user = await get_user(user_id)
except UserNotFoundError:
    raise NotFoundError("User", user_id)
```

## FastAPI Integration

```python
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse

app = FastAPI()

@app.exception_handler(APIError)
async def api_error_handler(request: Request, exc: APIError):
    """Global exception handler for APIError."""
    return JSONResponse(
        status_code=exc.status_code,
        content=exc.to_dict()
    )

@app.exception_handler(Exception)
async def general_exception_handler(request: Request, exc: Exception):
    """Catch-all for unexpected errors."""
    error_response = create_error_response(
        "Internal server error",
        status_code=500,
        details={"type": type(exc).__name__}
    )
    # Log full error but don't expose to client
    logger.error(f"Unexpected error: {exc}", exc_info=True)
    return JSONResponse(status_code=500, content=error_response)
```

## Security Note

**Never include in errors:**
- Raw API response text
- Stack traces (log them, don't return them)
- Internal IDs or tokens
- Database query details
- Full exception messages from external APIs
- Authentication credentials
- File paths or system information

**Safe to include:**
- User-facing error messages
- Validation field names
- Request IDs for support
- Status codes
- Generic error types

## Logging Errors

```python
import logging

logger = logging.getLogger(__name__)

def handle_error(error: Exception, context: dict = None) -> dict:
    """Handle error with proper logging and structured response."""
    request_id = str(uuid.uuid4())

    # Log with context
    logger.error(
        f"Error occurred | request_id={request_id} | "
        f"error={type(error).__name__}",
        extra=context,
        exc_info=True
    )

    # Return safe error response
    return create_error_response(
        "An error occurred processing your request",
        status_code=500,
        details={"request_id": request_id}
    )
```

## ❌ Anti-Patterns

```python
# ❌ Leaking internal errors
return {"error": str(exception)}

# ❌ Inconsistent format across endpoints
def endpoint1(): return "Error"
def endpoint2(): return {"error": "Error"}

# ❌ No context for debugging
return {"error": "Failed"}

# ❌ Returning 200 with error in body
return {"success": False, "error": "..."}  # Should use proper status code

# ❌ Too much information
return {
    "error": f"Database query failed: {full_sql_query}",
    "stacktrace": traceback.format_exc()
}
```

## Best Practices Checklist

- ✅ Use consistent error structure across application
- ✅ Include request_id for tracing
- ✅ Include timestamp for debugging
- ✅ Use proper HTTP status codes
- ✅ Create custom exception classes for common errors
- ✅ Add global exception handlers
- ✅ Log full error details (with context)
- ✅ Return safe, user-friendly messages
- ✅ Never expose sensitive data in errors
- ✅ Document error responses in API docs

## Auto-Apply

When you write error handling:
1. Create helper `create_error_response()`
2. Use it for all error returns
3. Include request_id and timestamp
4. Remove any sensitive data
5. Use proper status codes

## Related Skills

- docstring-format - Document Raises section
- pii-redaction - Redact PII in error logs
- pydantic-models - For error response models

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.