소스 정보
- 저장소
- ffsshhttiikk/opencode-agents-skills
- 최근 소스 활동
- 2026년 2월 28일 22:51
- 감지된 SKILL.md 언어
- 영어
- 스타
- 2
- 포크
- 2
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/ffsshhttiikk/opencode-agents-skills --skill error-handling명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | error-handling |
| description | Error handling best practices and patterns |
| license | MIT |
| compatibility | opencode |
| metadata | {"audience":"developers","category":"programming"} |
When implementing error handling or designing exception strategies.
from abc import ABC
from typing import Optional, Dict, Any
import traceback
class AppException(ABC):
"""Base exception for application errors."""
def __init__(
self,
message: str,
code: str,
status_code: int = 500,
details: Optional[Dict[str, Any]] = None,
cause: Optional[Exception] = None,
) -> None:
self.message = message
self.code = code
self.status_code = status_code
self.details = details or {}
self.cause = cause
super().__init__(message)
def to_dict(self) -> Dict[str, Any]:
"""Convert exception to dictionary."""
return {
"error": {
"code": self.code,
"message": self.message,
"details": self.details,
}
}
class ValidationError(AppException):
"""Raised when input validation fails."""
def __init__(
self,
message: str,
field: Optional[str] = None,
value: Any = None,
details: Optional[Dict[str, Any]] = None,
) -> None:
error_details = details or {}
if field:
error_details["field"] = field
if value is not None:
error_details["value"] = str(value)
super().__init__(
message=message,
code="VALIDATION_ERROR",
status_code=400,
details=error_details,
)
class NotFoundError(AppException):
"""Raised when a resource is not found."""
def __init__(
self,
resource_type: str,
resource_id: str,
details: Optional[Dict[str, Any]] = None,
) -> None:
super().__init__(
message=f"{resource_type} with ID '{resource_id}' not found",
code="NOT_FOUND",
status_code=404,
details=details or {"resource_type": resource_type, "id": resource_id},
)
class ConflictError(AppException):
"""Raised when there's a resource conflict."""
def __init__(
self,
message: str,
details: Optional[Dict[str, Any]] = None,
) -> None:
super().__init__(
message=message,
code="CONFLICT",
status_code=409,
details=details,
)
class AuthenticationError(AppException):
"""Raised when authentication fails."""
def __init__(
self,
message: str = "Authentication required",
details: Optional[Dict[str, Any]] = None,
) -> None:
super().__init__(
message=message,
code="UNAUTHORIZED",
status_code=401,
details=details,
)
class AuthorizationError(AppException):
"""Raised when user is not authorized."""
def __init__(
self,
message: str = "Access denied",
details: Optional[Dict[str, Any]] = None,
) -> None:
super().__init__(
message=message,
code="FORBIDDEN",
status_code=403,
details=details,
)
class RateLimitError(AppException):
"""Raised when rate limit is exceeded."""
def __init__(
self,
retry_after: int = 60,
details: Optional[Dict[str, Any]] = None,
) -> None:
super().__init__(
message="Rate limit exceeded. Please retry later.",
code="RATE_LIMIT_EXCEEDED",
status_code=429,
details=details or {"retry_after": retry_after},
)
class ExternalServiceError(AppException):
"""Raised when external service call fails."""
def __init__(
self,
service_name: str,
message: str,
status_code: int = 503,
details: Optional[Dict[str, Any]] = None,
) -> None:
super().__init__(
message=f"External service error: {service_name}",
code="EXTERNAL_SERVICE_ERROR",
status_code=status_code,
details=details or {"service": service_name},
)
import logging
from fastapi import Request, HTTPException
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware
logger = logging.getLogger(__name__)
class ErrorHandlingMiddleware(BaseHTTPMiddleware):
"""Handle exceptions and convert to HTTP responses."""
async def dispatch(self, request: Request, call_next):
try:
response = await call_next(request)
return response
except AppException as e:
logger.warning(
f"App error: {e.code} - {e.message}",
extra={
"code": e.code,
"status_code": e.status_code,
"details": e.details,
"path": request.url.path,
}
)
return JSONResponse(
status_code=e.status_code,
content=e.to_dict(),
headers={"X-Error-Code": e.code},
)
except HTTPException as e:
return JSONResponse(
status_code=e.status_code,
content={"error": {"code": "HTTP_ERROR", "message": e.detail}},
)
except ValueError as e:
logger.warning(f"Validation error: ", extra={: request.url.path})
JSONResponse(
status_code=,
content={
: {
: ,
: (e),
}
},
)
Exception e:
logger.error(
,
extra={
: traceback.format_exc(),
: request.url.path,
}
)
JSONResponse(
status_code=,
content={
: {
: ,
: ,
}
},
)
from typing import Generic, TypeVar, Union, Optional
T = TypeVar('T')
class Result(Generic[T]):
"""
Result type for operations that can fail.
Provides safe error handling without exceptions.
"""
def __init__(
self,
value: Optional[T] = None,
error: Optional[Exception] = None,
) -> None:
self._value = value
self._error = error
@classmethod
def success(cls, value: T) -> 'Result[T]':
"""Create a successful result."""
return cls(value=value)
@classmethod
def failure(cls, error: Exception) -> 'Result[T]':
"""Create a failed result."""
return cls(error=error)
@property
def is_success(self) -> bool:
"""Check if result is successful."""
return self._error is None
@property
def is_failure(self) -> :
._error
() -> T:
._value .is_success default
() -> [Exception]:
._error
() -> :
.is_success:
:
Result.success(func(._value))
Exception e:
Result.failure(e)
() -> :
.is_success:
func(._value)
() -> T:
._value .is_success default
() -> :
.is_success:
() -> Result[User]:
:
user = database.get_user(user_id)
user:
Result.failure(NotFoundError(, user_id))
Result.success(user)
DatabaseError e:
Result.failure(e)
result = get_user()
result.is_success:
user = result.get_value()
()
:
error = result.get_error()
()
import asyncio
from functools import wraps
from typing import Callable, TypeVar, List
import time
T = TypeVar('T')
class RetryConfig:
"""Configuration for retry behavior."""
def __init__(
self,
max_retries: int = 3,
base_delay: float = 1.0,
max_delay: float = 60.0,
exponential_base: float = 2.0,
jitter: float = 0.1,
retryable_exceptions: tuple = (Exception,),
) -> None:
self.max_retries = max_retries
self.base_delay = base_delay
self.max_delay = max_delay
self.exponential_base = exponential_base
self.jitter = jitter
self.retryable_exceptions = retryable_exceptions
def calculate_delay(self, attempt: int) -> float:
"""Calculate delay for attempt number."""
delay = self.base_delay * (self.exponential_base ** attempt)
delay = min(delay, self.max_delay)
# Add jitter
jitter_amount = delay * .jitter
delay += time.uniform(-jitter_amount, jitter_amount)
(, delay)
():
() -> [..., T]:
() -> T:
config = config RetryConfig()
last_exception =
attempt (config.max_retries + ):
:
func(*args, **kwargs)
config.retryable_exceptions e:
last_exception = e
attempt >= config.max_retries:
delay = config.calculate_delay(attempt)
(
)
asyncio.sleep(delay)
last_exception
() -> T:
config = config RetryConfig()
last_exception =
attempt (config.max_retries + ):
:
func(*args, **kwargs)
config.retryable_exceptions e:
last_exception = e
attempt >= config.max_retries:
delay = config.calculate_delay(attempt)
(
)
time.sleep(delay)
last_exception
async_wrapper asyncio.iscoroutinefunction(func) sync_wrapper
decorator
() -> :
aiohttp.ClientSession() session:
session.get(url) response:
response.raise_for_status()
response.json()
HTTP Status Codes:
400 - Bad Request (validation, malformed)
401 - Unauthorized (authentication required)
403 - Forbidden (not authorized)
404 - Not Found (resource doesn't exist)
409 - Conflict (state conflict)
422 - Unprocessable Entity (validation errors)
429 - Too Many Requests (rate limit)
500 - Internal Server Error
502 - Bad Gateway
503 - Service Unavailable
504 - Gateway Timeout
Application Error Codes:
VALIDATION_ERROR - Input validation failed
NOT_FOUND - Resource not found
CONFLICT - State conflict
UNAUTHORIZED - Authentication required
FORBIDDEN - Not authorized
RATE_LIMIT_EXCEEDED - Rate limit hit
EXTERNAL_SERVICE_ERROR - External service failed
TIMEOUT - Operation timed out
PERMISSION_DENIED - Insufficient permissions
DUPLICATE_ENTRY - Resource already exists
1. Use specific exception types
Don't catch generic Exception
2. Include context in errors
What happened? Where? What caused it?
3. Log exceptions appropriately
DEBUG for expected, ERROR for unexpected
4. Don't expose internals
Don't leak stack traces to users
5. Handle failures gracefully
Provide helpful error messages
6. Use result types for recoverable errors
Exceptions for exceptional situations
7. Retry transient failures
Network issues, timeouts
8. Document error codes
For API consumers
9. Use proper HTTP status codes
Match semantics to status
10. Clean up resources in finally
Use context managers