Skip to main content Skills Marketplace Découvrez et explorez les compétences IA créées par la communauté.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Copier le promptAfficher les détails du prompt Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
npx skills add https://github.com/aaione/everything-claude-code-zh --skill error-handlingLa commande reste sur une seule ligne. Faites défiler horizontalement pour la vérifier avant de la copier.
Vous préférez une copie locale ? Téléchargez les fichiers actuellement disponibles dans SkillsMP.
Télécharger Zip Téléchargement... Métiers associés SOC
Basé sur la classification professionnelle SOC
name error-handling description TypeScript、Python 和 Go 中的健壮错误处理模式。涵盖类型化错误、错误边界、重试、熔断器和面向用户的错误消息。 origin ECC
错误处理模式
适用于生产应用的一致、健壮的错误处理模式。
何时激活
为新模块或服务设计错误类型或异常层次结构
为不可靠的外部依赖添加重试逻辑或熔断器
审查 API 端点的错误处理缺失
实现面向用户的错误消息和反馈
调试级联故障或静默错误吞没
核心原则
快速且大声地失败 ——在错误发生的边界暴露错误;不要埋没它们
类型化错误优于字符串消息 ——错误是具有结构的一等值
用户消息 ≠ 开发者消息 ——向用户显示友好文本,在服务端记录完整上下文
永远不要静默吞没错误 ——每个 catch 块必须处理、重新抛出或记录
错误是 API 契约的一部分 ——记录客户端可能收到的每个错误码
TypeScript / JavaScript
类型化错误类
export class AppError extends Error {
constructor (
message : string ,
public readonly code : string ,
public readonly statusCode : number = ,
?: ,
) {
(message)
. = . .
. ( , . . )
}
}
{
( ) {
( , , )
}
}
{
( ) {
(message, , , details)
}
}
{
( ) {
(reason, , )
}
}
{
( ) {
( , , )
}
}
500
public
readonly
details
unknown
super
this
name
this
constructor
name
Object
setPrototypeOf
this
new
target
prototype
export
class
NotFoundError
extends
AppError
constructor
resource : string , id : string
super
`${resource} 未找到: ${id} `
'NOT_FOUND'
404
export
class
ValidationError
extends
AppError
constructor
message : string , details : { field: string ; message: string }[]
super
'VALIDATION_ERROR'
422
export
class
UnauthorizedError
extends
AppError
constructor
reason = '需要认证'
super
'UNAUTHORIZED'
401
export
class
RateLimitError
extends
AppError
constructor
public readonly retryAfterMs : number
super
'超出速率限制'
'RATE_LIMITED'
429
Result 模式(非抛出风格) 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 }
}
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 ('数据库错误' , 'DB_ERROR' ))
}
}
const result = await fetchUser ('abc-123' )
if (!result.ok ) {
logger.error ('获取用户失败' , { error : result.error })
return
}
console .log (result.value .email )
API 错误处理器(Next.js / Express) import { NextRequest , NextResponse } from 'next/server'
function handleApiError (error : unknown ): NextResponse {
if (error instanceof AppError ) {
return NextResponse .json (
{
error : {
code : error.code ,
message : error.message ,
...(error.details ? { details : error.details } : {}),
},
},
{ status : error.statusCode },
)
}
if (error instanceof z.ZodError ) {
return NextResponse .json (
{
error : {
code : 'VALIDATION_ERROR' ,
message : '请求验证失败' ,
details : error.issues .map (i => ({
field : i.path .join ('.' ),
message : i.message ,
})),
},
},
{ status : 422 },
)
}
console .error ('意外错误:' , error)
return NextResponse .json (
{ error : { code : 'INTERNAL_ERROR' , message : '发生意外错误' } },
{ status : 500 },
)
}
export async function POST (req : NextRequest ) {
try {
} catch (error) {
return handleApiError (error)
}
}
React 错误边界 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 ('未处理的 React 错误:' , error, info)
}
render ( ) {
if (this .state .hasError ) return this .props .fallback
return this .props .children
}
}
<ErrorBoundary fallback={<p > 出了点问题。请刷新页面。</p > }>
<MyComponent />
</ErrorBoundary >
Python
自定义异常层次结构 class AppError (Exception ):
"""基础应用错误。"""
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} 未找到: {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 全局异常处理器 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:
logger.exception("意外错误" , exc_info=exc)
return JSONResponse(
status_code=500 ,
content={"error" : {"code" : "INTERNAL_ERROR" , "message" : "发生意外错误" }},
)
Go
哨兵错误和错误包装 package domain
import "errors"
var (
ErrNotFound = errors.New("未找到" )
ErrUnauthorized = errors.New("未授权" )
ErrConflict = errors.New("冲突" )
)
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("用户 %s: %w" , id, ErrNotFound)
}
if err != nil {
return nil , fmt.Errorf("查询用户 %s: %w" , id, err)
}
return user, nil
}
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" , "访问被拒绝" )
default :
slog.Error("意外错误" , "err" , err)
writeError(w, http.StatusInternalServerError, "internal_error" , "发生意外错误" )
}
return
}
writeJSON(w, http.StatusOK, user)
}
指数退避重试 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
}
const data = await withRetry (() => fetch ('/api/data' ).then (r => r.json ()), {
maxAttempts : 3 ,
retryIf : (error ) => !(error instanceof AppError && error.statusCode < 500 ),
})
面向用户的错误消息 将错误码映射为人类可读的消息。技术细节不要出现在用户可见的文本中。
const USER_ERROR_MESSAGES : Record <string , string > = {
NOT_FOUND : '无法找到请求的项目。' ,
UNAUTHORIZED : '请登录以继续。' ,
FORBIDDEN : '您没有执行此操作的权限。' ,
VALIDATION_ERROR : '请检查您的输入并重试。' ,
RATE_LIMITED : '请求过于频繁。请稍后再试。' ,
INTERNAL_ERROR : '我们的系统出了问题。请稍后再试。' ,
}
export function getUserMessage (code : string ): string {
return USER_ERROR_MESSAGES [code] ?? USER_ERROR_MESSAGES .INTERNAL_ERROR
}
错误处理检查清单