Skip to main content

Agent Skills Framework Extension

Error Debugging Patterns Skill

When to Use This Skill

Use this skill when implementing error debugging patterns patterns in your codebase.

How to Use This Skill

  1. Review the patterns and examples below
  2. Apply the relevant patterns to your implementation
  3. Follow the best practices outlined in this skill

Production error handling, analysis, and automated fix recommendations.

Core Capabilities

  1. Error Classification - Categorize and prioritize errors
  2. Fix Recommendations - Automated suggestions based on patterns
  3. Structured Logging - Consistent, queryable log formats
  4. Error Tracking - Aggregation, deduplication, alerting
  5. Recovery Strategies - Retry logic, circuit breakers

Structured Error System

// src/errors/structured_errors.rs
use thiserror::Error;
use serde::{Serialize, Deserialize};
use std::collections::HashMap;

#[derive(Error, Debug, Serialize)]
pub enum AppError {
#[error("Database error: {message}")]
Database {
message: String,
#[serde(skip)]
source: Option<sqlx::Error>,
context: ErrorContext,
},

#[error("Validation error: {field} - {message}")]
Validation {
field: String,
message: String,
context: ErrorContext,
},

#[error("External service error: {service}")]
ExternalService {
service: String,
status_code: Option<u16>,
context: ErrorContext,
},
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ErrorContext {
pub request_id: String,
pub user_id: Option<String>,
pub tenant_id: Option<String>,
pub timestamp: chrono::DateTime<chrono::Utc>,
pub metadata: HashMap<String, String>,
}

impl AppError {
pub fn fix_recommendation(&self) -> String {
match self {
AppError::Database { message, .. } => {
if message.contains("connection") {
"Check database connectivity and connection pool settings".to_string()
} else if message.contains("timeout") {
"Increase query timeout or optimize query performance".to_string()
} else {
"Review database logs and recent schema changes".to_string()
}
}
AppError::Validation { field, .. } => {
format!("Validate input for field '{}' before submission", field)
}
AppError::ExternalService { service, status_code, .. } => {
match status_code {
Some(429) => format!("Implement rate limiting for {} API calls", service),
Some(503) => format!("Add circuit breaker for {} service", service),
_ => format!("Check {} service health and credentials", service),
}
}
}
}

pub fn severity(&self) -> ErrorSeverity {
match self {
AppError::Database { .. } => ErrorSeverity::Critical,
AppError::Validation { .. } => ErrorSeverity::Warning,
AppError::ExternalService { status_code, .. } => {
match status_code {
Some(5..) => ErrorSeverity::Critical,
_ => ErrorSeverity::Error,
}
}
}
}
}

#[derive(Debug, Clone, Serialize)]
pub enum ErrorSeverity {
Warning,
Error,
Critical,
}

Error Tracking Integration

// src/errors/tracking.rs
use sentry::{ClientOptions, Level};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};

pub fn init_error_tracking() {
let _guard = sentry::init((
"https://key@sentry.io/project",
ClientOptions {
release: Some(env!("CARGO_PKG_VERSION").into()),
environment: Some(std::env::var("ENV").unwrap_or_else(|_| "development".into()).into()),
..Default::default()
},
));

tracing_subscriber::registry()
.with(tracing_subscriber::fmt::layer())
.with(sentry_tracing::layer())
.init();
}

pub fn report_error(error: &AppError) {
sentry::capture_error(error);

sentry::configure_scope(|scope| {
scope.set_tag("severity", error.severity().to_string());
scope.set_context("error_context", serde_json::to_value(&error.context).unwrap());

if let Some(user_id) = &error.context.user_id {
scope.set_user(Some(sentry::User {
id: Some(user_id.clone()),
..Default::default()
}));
}
});
}

Structured Logging

// src/logging/structured.rs
use tracing::{info, error, warn, instrument};
use serde_json::json;

#[instrument(skip(conn))]
pub async fn process_request(
request_id: String,
user_id: String,
conn: &sqlx::PgPool
) -> Result<(), AppError> {
info!(
request_id = %request_id,
user_id = %user_id,
"Processing request"
);

match execute_query(conn).await {
Ok(result) => {
info!(
request_id = %request_id,
rows_affected = result,
"Request completed successfully"
);
Ok(())
}
Err(e) => {
error!(
request_id = %request_id,
error = %e,
fix_recommendation = %e.fix_recommendation(),
severity = ?e.severity(),
"Request failed"
);
Err(e)
}
}
}

Error Recovery with Retry

// src/errors/recovery.rs
use tokio::time::{sleep, Duration};
use std::future::Future;

pub async fn retry_with_backoff<F, Fut, T, E>(
mut f: F,
max_retries: u32,
base_delay: Duration,
) -> Result<T, E>
where
F: FnMut() -> Fut,
Fut: Future<Output = Result<T, E>>,
{
let mut retries = 0;

loop {
match f().await {
Ok(result) => return Ok(result),
Err(e) => {
if retries >= max_retries {
return Err(e);
}

let delay = base_delay * 2_u32.pow(retries);
tracing::warn!(
retry = retries + 1,
max_retries,
delay_ms = delay.as_millis(),
"Retrying after error"
);

sleep(delay).await;
retries += 1;
}
}
}
}

// Circuit breaker
pub struct CircuitBreaker {
failure_threshold: u32,
success_threshold: u32,
timeout: Duration,
state: CircuitState,
failure_count: u32,
success_count: u32,
}

enum CircuitState {
Closed,
Open,
HalfOpen,
}

impl CircuitBreaker {
pub async fn call<F, Fut, T, E>(&mut self, f: F) -> Result<T, E>
where
F: FnOnce() -> Fut,
Fut: Future<Output = Result<T, E>>,
{
match self.state {
CircuitState::Open => {
Err(/* CircuitOpen error */)
}
CircuitState::Closed | CircuitState::HalfOpen => {
match f().await {
Ok(result) => {
self.on_success();
Ok(result)
}
Err(e) => {
self.on_failure();
Err(e)
}
}
}
}
}

fn on_success(&mut self) {
self.failure_count = 0;
self.success_count += 1;

if self.success_count >= self.success_threshold {
self.state = CircuitState::Closed;
}
}

fn on_failure(&mut self) {
self.success_count = 0;
self.failure_count += 1;

if self.failure_count >= self.failure_threshold {
self.state = CircuitState::Open;
}
}
}

Usage Examples

Error Analysis

Apply error-debugging-patterns skill to implement structured error system with fix recommendations

Error Tracking

Apply error-debugging-patterns skill to integrate Sentry error tracking with context

Recovery Patterns

Apply error-debugging-patterns skill to add retry logic with exponential backoff and circuit breaker

Success Output

When this skill completes successfully, output:

✅ SKILL COMPLETE: error-debugging-patterns

Completed:
- [x] Structured error system implemented (AppError enum)
- [x] Error classification with severity levels
- [x] Fix recommendations automated
- [x] Error tracking integrated (Sentry/tracing)
- [x] Structured logging with tracing instrumentation
- [x] Recovery strategies implemented (retry + circuit breaker)

Outputs:
- Error types: Database, Validation, ExternalService
- Error context: request_id, user_id, tenant_id, timestamp, metadata
- Severity levels: Warning, Error, Critical
- Fix recommendations: Automated suggestions per error type
- Tracking integration: Sentry with context and user info
- Recovery patterns: Retry with exponential backoff, circuit breaker

Completion Checklist

Before marking this skill as complete, verify:

  • AppError enum defines all error categories
  • ErrorContext includes request_id, user_id, tenant_id
  • fix_recommendation() method implemented for each error type
  • severity() method returns appropriate ErrorSeverity
  • Sentry error tracking initialized
  • Structured logging with tracing instrumentation
  • Retry logic with exponential backoff implemented
  • Circuit breaker pattern integrated
  • Unit tests cover error classification and recommendations

Failure Indicators

This skill has FAILED if:

  • ❌ AppError enum missing or incomplete (missing error categories)
  • ❌ ErrorContext missing required fields (request_id, user_id, etc.)
  • ❌ fix_recommendation() returns generic "check logs" messages
  • ❌ severity() not implemented or always returns same level
  • ❌ Sentry not initialized or not capturing errors
  • ❌ Logging not structured (missing tracing instrumentation)
  • ❌ Retry logic missing or uses fixed delay (no exponential backoff)
  • ❌ Circuit breaker missing or doesn't transition states

When NOT to Use

Do NOT use this skill when:

  • Building simple scripts with basic error handling (use Result<T, E>)
  • Implementing application-specific business logic errors (create custom error types)
  • Working with validation-only logic (use validation frameworks like validator)
  • Need synchronous error handling only (this includes async patterns)
  • Building CLI tools with simple error output (use anyhow or eyre)
  • Need language-specific error patterns (use language-specific skills)
  • Working on frontend error handling (use frontend error patterns)

Use alternatives:

  • rust-error-handling - For Rust-specific error handling without production patterns
  • validation-patterns - For input validation and data validation
  • logging-patterns - For general logging without error tracking integration
  • typescript-error-handling - For TypeScript/JavaScript error patterns

Anti-Patterns (Avoid)

Anti-PatternProblemSolution
Generic error messagesCannot diagnose root causeSpecific error types with context
Missing error contextNo request/user traceabilityInclude request_id, user_id, tenant_id
No severity classificationAll errors treated equallyClassify as Warning/Error/Critical
Hardcoded fix recommendationsNot helpful, outdatedGenerate recommendations based on error details
Ignoring error trackingCannot monitor production issuesIntegrate Sentry or equivalent
Unstructured logsCannot query/analyzeUse tracing instrumentation
Fixed retry delayThundering herd problemExponential backoff with jitter
No circuit breakerCascading failuresImplement circuit breaker for external services
Swallowing errorsSilent failuresAlways log and report errors

Principles

This skill embodies these CODITECT principles:

  • #1 Observable Errors - Structured logging and error tracking for visibility
  • #2 Actionable Recommendations - Automated fix suggestions based on error patterns
  • #3 Context Preservation - ErrorContext captures request, user, tenant for debugging
  • #5 Eliminate Ambiguity - Specific error types with clear severity levels
  • #6 Clear, Understandable - Error messages explain what happened and how to fix
  • #7 Resilient Recovery - Retry logic and circuit breakers prevent cascading failures
  • #8 No Assumptions - Verify error severity and context before reporting

Reference: CODITECT-STANDARD-AUTOMATION.md


Integration Points

  • debugging-patterns - Root cause analysis
  • rust-development-patterns - Rust error handling
  • cicd-automation-patterns - Error monitoring in pipelines