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
- Review the patterns and examples below
- Apply the relevant patterns to your implementation
- Follow the best practices outlined in this skill
Production error handling, analysis, and automated fix recommendations.
Core Capabilities
- Error Classification - Categorize and prioritize errors
- Fix Recommendations - Automated suggestions based on patterns
- Structured Logging - Consistent, queryable log formats
- Error Tracking - Aggregation, deduplication, alerting
- 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-Pattern | Problem | Solution |
|---|---|---|
| Generic error messages | Cannot diagnose root cause | Specific error types with context |
| Missing error context | No request/user traceability | Include request_id, user_id, tenant_id |
| No severity classification | All errors treated equally | Classify as Warning/Error/Critical |
| Hardcoded fix recommendations | Not helpful, outdated | Generate recommendations based on error details |
| Ignoring error tracking | Cannot monitor production issues | Integrate Sentry or equivalent |
| Unstructured logs | Cannot query/analyze | Use tracing instrumentation |
| Fixed retry delay | Thundering herd problem | Exponential backoff with jitter |
| No circuit breaker | Cascading failures | Implement circuit breaker for external services |
| Swallowing errors | Silent failures | Always 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