Skills Plugins MCP Prompt Model 博客 我的中心
Development #python #typescript #design #ai

error-handling

Patterns for robust error handling across TypeScript, Python, and Go. Covers typed errors, error boundaries, retries, circuit breakers, and user-facing error messages. Use when designing error types, retries, circuit breakers, or user-facing failure messages in TypeScript, Python, or Go.

DeepseekModel Curated skill Quality Excellent · 90 v1.0.0

Get

https://deepseekmodel.com/api/download.php?id=affaan-m-ecc-skills-error-handling-skill-md&format=skill
Download .skill Standard format with system_prompt and model_config, ready for any agent framework
The actual content of the system_prompt field in the .skill file.
name error-handling description Patterns for robust error handling across TypeScript, Python, and Go. Covers typed errors, error boundaries, retries, circuit breakers, and user-facing error messages. Use when designing error types, retries, circuit breakers, or user-facing failure messages in TypeScript, Python, or Go. metadata {"origin":"ECC"} Error Handling Patterns Consistent, robust error handling patterns for production applications. When to Activate Designing error types or exception hierarchies for a new module or service Adding retry logic or circuit breakers for unreliable external dependencies Reviewing API endpoints for missing error handling Implementing user-facing error messages and feedback Debugging cascading failures or silent error swallowing Core Principles Fail fast and loudly — surface errors at the boundary where they occur; don't bury them Typed errors over string messages — errors are first-class values with structure User messages ≠ developer messages — show friendly text to users, log full context server-side Never swallow errors silently — every catch block must either handle, re-throw, or log Errors are part of your API contract — document every error code a client may receive TypeScript / JavaScript Typed Error Classes // Define an error hierarchy for your domain export class AppError extends Error { constructor ( message : string , public readonly code : string , public readonly statusCode : number = 500 , public readonly details ?: unknown , ) { super (message) this . name = this . constructor . name // Maintain correct prototype chain in transpiled ES5 JavaScript. // Required for `instanceof` checks (e.g., `error instanceof NotFoundError`) // to work correctly when extending the built-in Error class. Object . setPrototypeOf ( this , new . target . prototype ) } } export class NotFoundError extends AppError { constructor ( resource : string , id : string ) { super ( ` ${resource} not found: ${id} ` , 'NOT_FOUND' , 404 ) } } export class ValidationError extends AppError { constructor ( message : string , details : { field: string ; message: string }[] ) { super (message, 'VALIDATION_ERROR' , 422 , details) } } export class UnauthorizedError extends AppError { constructor ( reason = 'Authentication required' ) { super (reason, 'UNAUTHORIZED' , 401 ) } } export class RateLimitError extends AppError { constructor ( public readonly retryAfterMs : number ) { super ( 'Rate limit exceeded' , 'RATE_LIMITED' , 429 ) } } Result Pattern (no-throw style) For operations where failure is expected and common (parsing, external calls): type Result <T, E = AppError > = | { ok : true ; value : T } | { ok : false ; error : E } function ok<T>( value : T): Result <T> { return { ok : true , value } } function err<E>( error : E): Result < never , E> { return { ok : false , error } } // Usage async function fetchUser ( id : string ): Promise < Result < User >> { try { const user = await db. users . findUnique ({ where : { id } }) if (!user) return err ( new NotFoundError ( 'User' , id)) return ok (user) } catch (e) { return err ( new AppError ( 'Database error' , 'DB_ERROR' )) } } const result = await fetchUser ( 'abc-123' ) if (!result. ok ) { // TypeScript knows result.error here logger. error ( 'Failed to fetch user' , { error : result. error }) return } // TypeScript knows result.value here console . log (result. value . email ) API Error Handler (Next.js / Express) import { NextRequest , NextResponse } from 'next/server' function handleApiError ( error : unknown ): NextResponse { // Known application error if (error instanceof AppError ) { return NextResponse . json ( { error : { code : error. code , message : error. message , ...(error. details ? { details : error. details } : {}), }, }, { status : error. statusCode }, ) } // Zod validation error if (error instanceof z. ZodError ) { return NextResponse . json ( { error : { code : 'VALIDATION_ERROR' , message : 'Request validation failed' , details : error. issues . map ( i => ({ field : i. path . join ( '.' ), message : i. message , })), }, }, { status : 422 }, ) } // Unexpected error — log details, return generic message console . error ( 'Unexpected error:' , error) return NextResponse . json ( { error : { code : 'INTERNAL_ERROR' , message : 'An unexpected error occurred' } }, { status : 500 }, ) } export async function POST ( req : NextRequest ) { try { // ... handler logic } catch (error) { return handleApiError (error) } } React Error Boundary import { Component , ErrorInfo , ReactNode } from 'react' interface Props { fallback : ReactNode onError ?: ( error : Error , info : ErrorInfo ) => void children : ReactNode } interface State { hasError : boolean error : Error | null } export class ErrorBoundary extends Component < Props , State > { state : State = { hasError : false , error : null } static getDerivedStateFromError ( error : Error ): State { return { hasError : true , error } } componentDidCatch ( error : Error , info : ErrorInfo ) { this . props . onError ?.(error, info) console . error ( 'Unhandled React error:' , error, info) } render ( ) { if ( this . state . hasError ) return this . props . fallback return this . props . children } } // Usage < ErrorBoundary fallback={ < p > Something went wrong. Please refresh. </ p > }> < MyComponent /> </ ErrorBoundary > Python Custom Exception Hierarchy class AppError ( Exception ): """Base application error.""" def __init__ ( self, message: str , code: str , status_code: int = 500 ): super ().__init__(message) self .code = code self .status_code = status_code class NotFoundError ( AppError ): def __init__ ( self, resource: str , id : str ): super ().__init__( f" {resource} not found: { id } " , "NOT_FOUND" , 404 ) class ValidationError ( AppError ): def __init__ ( self, message: str , details: list [ dict ] | None = None ): super ().__init__(message, "VALIDATION_ERROR" , 422 ) self .details = details or [] FastAPI Global Exception Handler from fastapi import FastAPI, Request from fastapi.responses import JSONResponse app = FastAPI() @app.exception_handler( AppError ) async def app_error_handler ( request: Request, exc: AppError ) -> JSONResponse: return JSONResponse( status_code=exc.status_code, content={ "error" : { "code" : exc.code, "message" : str (exc)}}, ) @app.exception_handler( Exception ) async def generic_error_handler ( request: Request, exc: Exception ) -> JSONResponse: # Log full details, return generic message logger.exception( "Unexpected error" , exc_info=exc) return JSONResponse( status_code= 500 , content={ "error" : { "code" : "INTERNAL_ERROR" , "message" : "An unexpected error occurred" }}, ) Go Sentinel Errors and Error Wrapping package domain import "errors" // Sentinel errors for type-checking var ( ErrNotFound = errors.New( "not found" ) ErrUnauthorized = errors.New( "unauthorized" ) ErrConflict = errors.New( "conflict" ) ) // Wrap errors with context — never lose the original func (r *UserRepository) FindByID(ctx context.Context, id string ) (*User, error ) { user, err := r.db.QueryRow(ctx, "SELECT * FROM users WHERE id = $1" , id) if errors.Is(err, sql.ErrNoRows) { return nil , fmt.Errorf( "user %s: %w" , id, ErrNotFound) } if err != nil { return nil , fmt.Errorf( "querying user %s: %w" , id, err) } return user, nil } // At the handler level, unwrap to determine response func (h *Handler) GetUser(w http.ResponseWriter, r *http.Request) { user, err := h.service.GetUser(r.Context(), chi.URLParam(r, "id" )) if err != nil { switch { case errors.Is(err, domain.ErrNotFound): writeError(w, http.StatusNotFound, "not_found" , err.Error()) case errors.Is(err, domain.ErrUnauthorized): writeError(w, http.StatusForbidden, "forbidden" , "Access denied" ) default : slog.Error( "unexpected error" , "err" , err) writeError(w, http.StatusInternalServerError, "internal_error" , "An unexpected error occurred" ) } return } writeJSON(w, http.StatusOK, user) } Retry with Exponential Backoff interface RetryOptions { maxAttempts ?: number baseDelayMs ?: number maxDelayMs ?: number retryIf ?: ( error : unknown ) => boolean } async function withRetry<T>( fn : () => Promise <T>, options : RetryOptions = {}, ): Promise <T> { const { maxAttempts = 3 , baseDelayMs = 500 , maxDelayMs = 10_000 , retryIf = () => true , } = options let lastError : unknown for ( let attempt = 1 ; attempt <= maxAttempts; attempt++) { try { return await fn () } catch (error) { lastError = error if (attempt === maxAttempts || ! retryIf (error)) throw error const jitter = Math . random () * baseDelayMs const delay = Math . min (baseDelayMs * 2 ** (attempt - 1 ) + jitter, maxDelayMs) await new Promise ( resolve => setTimeout (resolve, delay)) } } throw lastError } // Usage: retry transient network errors, not 4xx const data = await withRetry ( () => fetch ( '/api/data' ). then ( r => r. json ()), { maxAttempts : 3 , retryIf : ( error ) => !(error instanceof AppError && error. statusCode < 500 ), }) User-Facing Error Messages Map error codes to human-readable messages. Keep technical details out of user-visible text. const USER_ERROR_MESSAGES : Record < string , string > = { NOT_FOUND : 'The requested item could not be found.' , UNAUTHORIZED : 'Please sign in to continue.' , FORBIDDEN : "You don't have permission to do that." , VALIDATION_ERROR : 'Please check your input and try again.' , RATE_LIMITED : 'Too many requests. Please wait a moment and try again.' , INTERNAL_ERROR : 'Something went wrong on our end. Please try again later.' , } export function getUserMessage ( code : string ): string { return USER_ERROR_MESSAGES [code] ?? USER_ERROR_MESSAGES . INTERNAL_ERROR } Error Handling Checklist Before merging any code that touches error handling: Every catch block handles, re-throws, or logs — no silent swallowing API errors follow the standard envelope { error: { code, message } } User-facing messages contain no stack traces or internal details Full error context is logged server-side Custom error classes extend a base AppError with a code field Async functions surface errors to callers — no fire-and-forget without fallback Retry logic only retries retriable errors (not 4xx client errors) React components are wrapped in ErrorBoundary for rendering errors
Keywords that activate this skill. Click one to copy it.

This skill does not provide trigger words.

The downloaded .skill package contains the following fields.
Field Description
formatFormat tag (skill/v1)
skill_idUnique skill ID
nameSkill name
versionVersion
descriptionDescription
categoryCategories (array)
trigger_wordsTrigger words
tagsTags
sourceSource
source_urlSource URL (this page)
exported_atExported at (set per download)
system_promptSystem prompt body
model_configModel config: provider / model / temperature / max_tokens / top_p
examplesExamples
install_guideImport guide for Coze / Dify / Claude / custom frameworks
The same skill can be exported in different platform formats.
.skill Standard format with system_prompt and model_config, ready for any agent framework Download
.skillpro Enhanced format with scripts, tools, dependencies and hooks Download
.json Plain JSON export with system_prompt and model parameters only Download
Coze Markdown with frontmatter, for Coze platform import Download
Dify Dify DSL, import directly after creating an app Download

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。