Token导航 LogoToken导航TokenDH.com
开发需要联网github未标认证来源可访问clear审计通过

error-handling-patterns错误处理模式

Agent Skill

error-handling-patterns 用于记录任务执行中的错误、用户纠正、经验和能力缺口,适合在 Codex、Claude、Cursor、Gemini CLI 中希望让 Agent 持续沉淀问题、修正和最佳实践时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

392

周安装

16

GitHub Stars

8

下载量

127
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:error-handling-patterns(错误处理模式)
来源仓库:https://github.com/kaakati/rails-enterprise-dev
仓库路径:skills/error-handling-patterns
安装命令:
npx skills add https://github.com/kaakati/rails-enterprise-dev --skill error-handling-patterns
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/kaakati/rails-enterprise-dev --skill error-handling-patterns

简介

记录任务执行中的错误案例与修正经验,形成可复用模式库。

  • 适合在 Codex、Claude、Cursor、Gemini CLI 中持续优化 Agent 行为。
  • 通过 GitHub 仓库安装,使用 npx skills add 命令添加技能。
  • 需定期维护条目准确性,避免过时信息误导后续操作。
  • 建议结合具体场景标注适用条件和例外情况。

SKILL.md

Error Handling Patterns — Expert Decisions

Expert decision frameworks for error handling choices. Claude knows Swift error syntax — this skill provides judgment calls for error type design and recovery strategies.


Decision Trees

throws vs Result

Does the caller need to handle success/failure explicitly?
├─ YES (caller must acknowledge failure)
│  └─ Is the failure common and expected?
│     ├─ YES → Result<T, E> (explicit handling, no try/catch)
│     └─ NO → throws (exceptional case)
│
└─ NO (caller can ignore failure)
   └─ Use throws with try? at call site

When Result wins: Parsing, validation, operations where failure is common and needs explicit handling. Forces exhaustive switch.

When throws wins: Network calls, file operations where failure is exceptional. Cleaner syntax with async/await.

Error Type Granularity

How specific should error types be?
├─ API boundary (framework, library)
│  └─ Coarse-grained domain errors
│     enum NetworkError: Error { case timeout, serverError, ... }
│
├─ Internal module
│  └─ Fine-grained for actionable handling
│     enum PaymentError: Error {
│         case cardDeclined(reason: String)
│         case insufficientFunds(balance: Decimal, required: Decimal)
│     }
│
└─ User-facing
   └─ LocalizedError with user-friendly messages
      var errorDescription: String? { "Payment failed" }

The trap: Too many error types that no one handles differently. If every case has the same handler, collapse them.

Recovery Strategy Selection

Is the error transient (network, timeout)?
├─ YES → Is it idempotent?
│  ├─ YES → Retry with exponential backoff
│  └─ NO → Retry cautiously or fail
│
└─ NO → Is recovery possible?
   ├─ YES → Can user fix it?
   │  ├─ YES → Show actionable error UI
   │  └─ NO → Auto-recover or fallback value
   │
   └─ NO → Log and show generic error

Error Presentation Selection

How critical is the failure?
├─ Critical (can't continue)
│  └─ Full-screen error with retry
│
├─ Important (user needs to know)
│  └─ Alert dialog
│
├─ Minor (informational)
│  └─ Toast or inline message
│
└─ Silent (user doesn't need to know)
   └─ Log only, use fallback

NEVER Do

Error Type Design

NEVER use generic catch-all errors:

// ❌ Caller can't handle different cases
enum AppError: Error {
    case somethingWentWrong
    case error(String)  // Just a message — no actionable info
}

// ✅ Specific, actionable cases
enum AuthError: Error {
    case invalidCredentials
    case sessionExpired
    case accountLocked(unlockTime: Date?)
}

NEVER throw errors with sensitive information:

// ❌ Leaks internal details
throw DatabaseError.queryFailed(sql: query, password: dbPassword)

// ✅ Sanitize sensitive data
throw DatabaseError.queryFailed(table: tableName)

NEVER create error enums with one case:

// ❌ Pointless enum
enum ValidationError: Error {
    case invalid
}

// ✅ Use existing error or don't create enum
struct ValidationError: Error {
    let field: String
    let reason: String
}

Error Propagation

NEVER swallow errors silently:

// ❌ Failure is invisible
func loadUser() async {
    try? await fetchUser()  // Error ignored, user is nil, no feedback
}

// ✅ Handle or propagate
func loadUser() async {
    do {
        user = try await fetchUser()
    } catch {
        errorMessage = error.localizedDescription
        analytics.trackError(error)
    }
}

NEVER catch and rethrow without adding context:

// ❌ Pointless catch
do {
    try operation()
} catch {
    throw error  // Why catch at all?
}

// ✅ Add context or handle
do {
    try operation()
} catch {
    throw ContextualError.operationFailed(underlying: error, context: "during checkout")
}

NEVER use force-try (try!) outside of known-safe scenarios:

// ❌ Crashes if JSON is malformed
let data = try! JSONEncoder().encode(untrustedInput)

// ✅ Safe scenarios only
let data = try! JSONEncoder().encode(staticKnownValue)  // Compile-time known
let url = URL(string: "https://example.com")!  // Literal string

// ✅ Handle unknown input
guard let data = try? JSONEncoder().encode(userInput) else {
    throw EncodingError.failed
}

CancellationError

NEVER show CancellationError to users:

// ❌ User sees "cancelled" error when navigating away
func loadData() async {
    do {
        data = try await fetchData()
    } catch {
        errorMessage = error.localizedDescription  // Shows "cancelled"
    }
}

// ✅ Handle cancellation separately
func loadData() async {
    do {
        data = try await fetchData()
    } catch is CancellationError {
        return  // User navigated away — not an error
    } catch {
        errorMessage = error.localizedDescription
    }
}

Retry Logic

NEVER retry non-idempotent operations blindly:

// ❌ May charge user multiple times
func processPayment() async throws {
    try await retryWithBackoff {
        try await chargeCard(amount)  // Not idempotent!
    }
}

// ✅ Use idempotency key or check state first
func processPayment() async throws {
    let idempotencyKey = UUID().uuidString
    try await retryWithBackoff {
        try await chargeCard(amount, idempotencyKey: idempotencyKey)
    }
}

NEVER retry without limits:

// ❌ Infinite loop if server is down
func fetch() async throws -> Data {
    while true {
        do {
            return try await request()
        } catch {
            try await Task.sleep(nanoseconds: 1_000_000_000)
        }
    }
}

// ✅ Limited retries with backoff
func fetch(maxAttempts: Int = 3) async throws -> Data {
    var delay: UInt64 = 1_000_000_000
    for attempt in 1...maxAttempts {
        do {
            return try await request()
        } catch where attempt < maxAttempts && isRetryable(error) {
            try await Task.sleep(nanoseconds: delay)
            delay *= 2
        }
    }
    throw FetchError.maxRetriesExceeded
}

Essential Patterns

Typed Error with Recovery Info

enum NetworkError: Error, LocalizedError {
    case noConnection
    case timeout
    case serverError(statusCode: Int)
    case unauthorized

    var errorDescription: String? {
        switch self {
        case .noConnection: return "No internet connection"
        case .timeout: return "Request timed out"
        case .serverError(let code): return "Server error (\(code))"
        case .unauthorized: return "Session expired"
        }
    }

    var recoverySuggestion: String? {
        switch self {
        case .noConnection: return "Check your network settings"
        case .timeout: return "Try again"
        case .serverError: return "Please try again later"
        case .unauthorized: return "Please log in again"
        }
    }

    var isRetryable: Bool {
        switch self {
        case .noConnection, .timeout, .serverError: return true
        case .unauthorized: return false
        }
    }
}

Result with Typed Error

func validate(email: String) -> Result<String, ValidationError> {
    guard !email.isEmpty else {
        return .failure(.emptyField("email"))
    }
    guard email.contains("@") else {
        return .failure(.invalidFormat("email"))
    }
    return .success(email)
}

// Forced exhaustive handling
switch validate(email: input) {
case .success(let email):
    createAccount(email: email)
case .failure(let error):
    showValidationError(error)
}

Retry with Exponential Backoff

func withRetry<T>(
    maxAttempts: Int = 3,
    initialDelay: Duration = .seconds(1),
    operation: () async throws -> T
) async throws -> T {
    var delay = initialDelay

    for attempt in 1...maxAttempts {
        do {
            return try await operation()
        } catch let error as NetworkError where error.isRetryable && attempt < maxAttempts {
            try await Task.sleep(for: delay)
            delay *= 2
        } catch {
            throw error
        }
    }
    fatalError("Should not reach")
}

Error Presentation in ViewModel

@MainActor
final class ViewModel: ObservableObject {
    @Published private(set) var state: State = .idle

    enum State: Equatable {
        case idle
        case loading
        case loaded(Data)
        case error(String, isRetryable: Bool)
    }

    func load() async {
        state = .loading
        do {
            let data = try await fetchData()
            state = .loaded(data)
        } catch is CancellationError {
            state = .idle  // Don't show error
        } catch let error as NetworkError {
            state = .error(error.localizedDescription, isRetryable: error.isRetryable)
        } catch {
            state = .error("Something went wrong", isRetryable: true)
        }
    }
}

Quick Reference

Error Handling Decision Matrix

ScenarioPatternWhy
Network callthrowsExceptional failure
ValidationResult<T, E>Expected failure, needs handling
Optional parsingtry?Failure acceptable, use default
Must succeedtry!Only for literals/static
Background taskLog onlyUser doesn't need to know

Error Type Checklist

  • Cases are actionable (handler differs per case)
  • No sensitive data in associated values
  • Conforms to LocalizedError for user-facing
  • Has isRetryable property if recovery is possible
  • Has recoverySuggestion for user guidance

Red Flags

SmellProblemFix
catch {} emptyError silently swallowedLog or propagate
Same handler for all casesOver-specific error typeCollapse to fewer cases
try? on critical pathHidden failuresUse do-catch
Retry without limitInfinite loop riskAdd max attempts
CancellationError shown to userBad UXHandle separately
error.localizedDescription on NSErrorTechnical messageMap to user-friendly

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Antigravity

30.42%
按下载量换算39

windsurf

22.43%
按下载量换算28

Claude Code

18.99%
按下载量换算24

OpenCode

13.37%
按下载量换算17

Gemini CLI

6.89%
按下载量换算9

Codex

3.65%
按下载量换算5

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills