errific

package module
v0.0.0-...-6aa9394 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 27, 2025 License: MIT Imports: 10 Imported by: 0

README

Errific

Errific Art

AI-Ready Error Handling for Go with caller metadata, clean error wrapping, structured context, error codes, retry metadata, and JSON serialization.

💡 Simple Example

package main

import (
	"fmt"
	"github.com/leefernandes/errific"
)

// Define your errors
var ErrUserNotFound errific.Err = "user not found"

func main() {
	// Configure pretty JSON output for readability
	errific.Configure(errific.OutputJSONPretty)

	// Return an error with context
	err := GetUser("user-123")
	fmt.Println(err)
}

func GetUser(userID string) error {
	// Simulate error with context
	return ErrUserNotFound.
		WithCode("USER_404").
		WithContext(errific.Context{
			"user_id": userID,
			"source":  "database",
		})
}

Output:

{
  "error": "user not found",
  "code": "USER_404",
  "caller": "main.go:27.GetUser",
  "context": {
    "source": "database",
    "user_id": "user-123"
  }
}

The error includes:

  • ✅ Automatic caller information (main.go:20.GetUser)
  • ✅ Error code (USER_404) visible in output
  • ✅ Structured context (user_id, source) visible in output
  • ✅ JSON output by default for structured logging

✨ Features

Core Features
  • 📍 Automatic Caller Information - File, line, and function automatically captured
  • 🔗 Clean Error Chaining - Native errors.Is and errors.As support
  • 🏷️ Error Codes & Categories - Machine-readable error classification
  • 📊 Structured Context - Attach metadata for debugging and analytics
  • 🔄 Retry Metadata - Built-in support for automated retry strategies
  • 🌐 HTTP Status Codes - Direct mapping to HTTP responses
  • 📦 JSON Serialization - Seamless integration with logging and APIs

MCP & RAG Integration

  • 🔗 MCP Error Format - JSON-RPC 2.0 compatible error responses for MCP servers
  • 🔍 Correlation Tracking - Correlation IDs, Request IDs, User IDs, Session IDs
  • 💡 Recovery Guidance - Help text, suggestions, and documentation links for AI self-healing
  • 🏷️ Semantic Tags - RAG-optimized tags for error categorization and search
  • 📌 Labels - Key-value labels for filtering, grouping, and alerting
  • Temporal Data - Timestamps and duration tracking
Quality
  • 🧵 Thread-Safe - Concurrent configuration and error creation
  • Lightweight - Small footprint, high performance
  • 🎯 98% Test Coverage - Comprehensive test suite with 72+ test cases, 13 benchmarks, 3 fuzz tests

🚀 Quick Start

Basic Usage
// Use Case: Basic error creation with automatic caller information
// Keywords: basic-usage, caller-info, error-wrapping, typed-errors

var ErrDatabaseQuery errific.Err = "database query failed"

// Two API styles - both work!

// Style 1: Explicit .New() (use when wrapping errors or caller info matters)
err := ErrDatabaseQuery.New(sqlErr)

// Style 2: Concise (recommended for new code)
err := ErrDatabaseQuery.WithCode("DB_001").WithHTTPStatus(500)

fmt.Println(err)
// Output: database query failed [myapp/db.go:42.QueryUsers]
// SQL error details...
AI-Ready Error Handling
// Use Case: AI-ready error with retry metadata and structured context
// Keywords: ai-ready, retry-logic, automated-recovery, structured-context

var ErrAPITimeout errific.Err = "API request timeout"

// Concise style (recommended) - no need to call .New() first
err := ErrAPITimeout.
    WithCode("API_TIMEOUT_001").
    WithCategory(errific.CategoryTimeout).
    WithContext(errific.Context{
        "endpoint":    "/v1/users",
        "duration_ms": 30000,
        "retry_count": 2,
    }).
    WithRetryable(true).
    WithRetryAfter(5 * time.Second).
    WithMaxRetries(3).
    WithHTTPStatus(504)

// AI agent can now automate responses
if errific.IsRetryable(err) {
    time.Sleep(errific.GetRetryAfter(err))
    // retry...
}

// Serialize for logging/monitoring
jsonBytes, _ := json.Marshal(err)
log.Info(string(jsonBytes))
🎨 Output Formats & Verbosity

Errific supports multiple output formats and verbosity levels. By default, errors output as JSON with all metadata visible.

// Default: JSON format with full verbosity (shows all metadata)
errific.Configure() // or Configure(OutputJSON, VerbosityFull)

err := ErrUserNotFound.
    WithCode("USER_404").
    WithContext(errific.Context{"user_id": "user-123"})

fmt.Println(err)
// Output: {"error":"user not found","code":"USER_404","caller":"main.go:20","context":{"user_id":"user-123"}}

// JSON Pretty format (indented JSON for docs/debugging)
errific.Configure(OutputJSONPretty)
fmt.Println(err)
// Output:
// {
//   "error": "user not found",
//   "code": "USER_404",
//   "caller": "main.go:20",
//   "context": {
//     "user_id": "user-123"
//   }
// }

// Pretty format (multi-line, human-readable text)
errific.Configure(OutputPretty)
fmt.Println(err)
// Output:
//   user not found [main.go:20.GetUser]
//     code: USER_404
//     context: map[user_id:user-123]

// Compact format (single-line key=value)
errific.Configure(OutputCompact)
fmt.Println(err)
// Output: user not found [main.go:20] code=USER_404 user_id=user-123

// Minimal verbosity (only message + caller, useful for simple logging)
errific.Configure(VerbosityMinimal)
fmt.Println(err)
// Output (JSON): {"error":"user not found","caller":"main.go:20"}

// Standard verbosity (message + caller + code + category + context)
errific.Configure(VerbosityStandard)
fmt.Println(err)
// Output (JSON): {"error":"user not found","code":"USER_404","caller":"main.go:20","context":{"user_id":"user-123"}}

// Custom verbosity (show only specific fields)
errific.Configure(VerbosityFull, HideContext, HideMCPData)
fmt.Println(err)
// Output (JSON): {"error":"user not found","code":"USER_404","caller":"main.go:20","http_status":404}

Available output formats:

  • OutputJSON (default) - Compact JSON for structured logging
  • OutputJSONPretty - Indented JSON for documentation and debugging
  • OutputPretty - Multi-line, human-readable text
  • OutputCompact - Single-line key=value pairs

Available verbosity levels:

  • VerbosityFull (default) - Show all non-empty fields
  • VerbosityStandard - Show code, category, context
  • VerbosityMinimal - Show only message and caller
  • VerbosityCustom - Use with Show*/Hide* flags for granular control

Granular field control: HideCode, HideCategory, HideContext, HideHTTPStatus, HideRetryMetadata, HideMCPData, HideTags, HideLabels, HideTimestamps

JSON Output
{
  "error": "API request timeout",
  "code": "API_TIMEOUT_001",
  "category": "timeout",
  "caller": "myapp/api.go:123.CallExternalService",
  "context": {
    "endpoint": "/v1/users",
    "duration_ms": 30000,
    "retry_count": 2
  },
  "retryable": true,
  "retry_after": "5s",
  "max_retries": 3,
  "http_status": 504
}
MCP Server Integration

Scenario: Your AI tool fails during execution and needs to return a proper MCP error response.

// Use Case: MCP tool server with rich error metadata for LLM consumption
// Keywords: mcp, json-rpc, llm-tools, ai-integration, error-recovery, claude

var ErrToolExecution errific.Err = "search_database tool failed"

// Create rich error with MCP metadata (concise style)
err := ErrToolExecution.New(dbErr).              // Still need .New() for wrapped errors
    WithMCPCode(errific.MCPToolError).           // JSON-RPC 2.0 error code
    WithCorrelationID("trace-abc-123").          // Track across distributed calls
    WithRequestID("req-456").                    // Individual request tracking
    WithHelp("Database connection pool exhausted").  // Human-readable help
    WithSuggestion("Increase pool size to 50").  // Actionable recovery step
    WithDocs("https://docs.ai/errors/db-pool").  // Documentation link
    WithTags("database", "connection-pool", "retryable"). // RAG semantic tags
    WithLabel("tool_name", "search_database").   // Filter/group by tool
    WithRetryable(true).
    WithRetryAfter(5 * time.Second)

// Or without wrapped error (even more concise):
err := ErrToolExecution.
    WithMCPCode(errific.MCPToolError).
    WithHelp("Database connection pool exhausted")
    // ... rest of chain

// Convert to MCP JSON-RPC 2.0 format
mcpErr := errific.ToMCPError(err)
json.NewEncoder(w).Encode(mcpErr)

MCP Response:

{
  "code": -32000,
  "message": "search_database tool failed",
  "data": {
    "error": "search_database tool failed",
    "code": "TOOL_001",
    "correlation_id": "trace-abc-123",
    "request_id": "req-456",
    "help": "Database connection pool exhausted",
    "suggestion": "Increase pool size to 50",
    "docs": "https://docs.ai/errors/db-pool",
    "tags": ["database", "connection-pool", "retryable"],
    "labels": {"tool_name": "search_database"},
    "retryable": true,
    "retry_after": "5s"
  }
}

Why This Matters:

  • 🤖 AI agents can self-heal using help/suggestion fields
  • 🔍 Correlation tracking across distributed MCP tool calls
  • 📊 RAG systems can categorize and search errors by semantic tags
  • 🎯 Monitoring systems can alert based on labels
  • 🔄 Automatic retry logic from metadata

🎯 Real-World Scenarios

Scenario 1: API Service Error Handling

Problem: Need consistent error responses across 50+ API endpoints

Solution: Use errific for automatic HTTP status mapping and JSON serialization

View Complete Example

Before (stdlib errors):

// Use Case: Traditional error handling without structure
// Keywords: stdlib, errors, no-http-status, manual-mapping

func GetUser(id string) (*User, error) {
    if id == "" {
        return nil, errors.New("invalid id")  // No status code, no structure
    }
    // API handler must manually map errors to HTTP status codes
}

After (errific):

// Use Case: Structured API errors with automatic HTTP status mapping
// Keywords: api, rest, http-status, validation, automatic-mapping

var ErrInvalidInput errific.Err = "invalid input"

func GetUser(id string) (*User, error) {
    if id == "" {
        return nil, ErrInvalidInput.New().
            WithCode("VAL_USER_ID").
            WithCategory(errific.CategoryValidation).
            WithHTTPStatus(400).
            WithContext(errific.Context{"field": "id"})
    }
    // ...
}

// API handler automatically gets status: GetHTTPStatus(err) → 400

Benefits:

  • ✅ Consistent error format across all endpoints
  • ✅ Automatic HTTP status code mapping
  • ✅ Structured context for debugging
  • ✅ JSON-ready for API responses
Scenario 2: Microservices with Distributed Tracing

Problem: Debugging errors across 10+ microservices is difficult

Solution: Use correlation IDs to trace errors through entire service chain

View Complete Example
// Use Case: Distributed tracing across microservices with correlation IDs
// Keywords: microservices, distributed-tracing, correlation-id, service-mesh, observability

// Service A (API Gateway)
func HandleRequest(w http.ResponseWriter, r *http.Request) {
    correlationID := uuid.New().String()
    user, err := userService.GetUser(ctx, userID, correlationID)
    if err != nil {
        // Correlation ID preserved through entire chain
        log.Error("request failed",
            "correlation_id", errific.GetCorrelationID(err),
            "service_chain", "gateway → user-service → db-service")
    }
}

// Service B (User Service)
func GetUser(ctx context.Context, id, correlationID string) (*User, error) {
    user, err := dbService.Query(ctx, id, correlationID)
    if err != nil {
        return nil, ErrUserQuery.New(err).
            WithCorrelationID(correlationID).
            WithLabel("service", "user-service")
    }
    return user, nil
}

// Service C (DB Service)
func Query(ctx context.Context, id, correlationID string) (*User, error) {
    if err := db.QueryRow(query, id).Scan(&user); err != nil {
        return nil, ErrDBQuery.New(err).
            WithCorrelationID(correlationID).  // Same ID!
            WithLabel("service", "db-service").
            WithContext(errific.Context{"query": query, "user_id": id})
    }
    return user, nil
}

Benefits:

  • ✅ Trace errors across entire service chain with single ID
  • ✅ Service labels for filtering in log aggregation
  • ✅ Context preserved at each layer
  • ✅ Easy debugging in distributed systems
Scenario 3: AI Agent with Self-Healing

Problem: AI agent needs to automatically retry failed API calls

Solution: Use retry metadata for intelligent, automated retry logic

View Complete Example
// Use Case: AI agent with automated retry logic based on error metadata
// Keywords: ai-agent, self-healing, retry-logic, automated-recovery, resilience

var ErrAPITimeout errific.Err = "external API timeout"

// Create API error with retry guidance
func CallExternalAPI(endpoint string) (*Response, error) {
    resp, err := httpClient.Get(endpoint)
    if err != nil {
        return nil, ErrAPITimeout.New(err).
            WithRetryable(true).
            WithRetryAfter(5 * time.Second).
            WithMaxRetries(3).
            WithHelp("External API is temporarily unavailable").
            WithSuggestion("Retry with exponential backoff")
    }
    return resp, nil
}

// AI agent automatically retries
func AIAgent_CallWithRetry(endpoint string) (*Response, error) {
    for attempt := 1; attempt <= 3; attempt++ {
        resp, err := CallExternalAPI(endpoint)
        if err == nil {
            return resp, nil  // Success!
        }

        // AI reads metadata and decides
        if !errific.IsRetryable(err) {
            break  // Don't retry non-retryable errors
        }

        if attempt >= errific.GetMaxRetries(err) {
            break  // Max retries reached
        }

        delay := errific.GetRetryAfter(err)
        log.Info("AI: Retrying", "attempt", attempt, "delay", delay)
        time.Sleep(delay)
    }
    return nil, err
}

Benefits:

  • ✅ AI makes intelligent retry decisions automatically
  • ✅ Help/suggestions guide recovery
  • ✅ Prevents retry storms with metadata
  • ✅ Exponential backoff built-in
Scenario 4: MCP Tool Server for LLMs

Problem: MCP tools need to return structured errors that LLMs can understand

Solution: Use MCP error format with recovery guidance for AI self-healing

View Complete Example
// Use Case: MCP tool server with LLM-readable error messages
// Keywords: mcp, tool-server, llm-integration, json-rpc, ai-tools, claude

var ErrToolExecution errific.Err = "search_database tool failed"

// MCP tool handler
func HandleSearchDatabase(params map[string]interface{}) (interface{}, error) {
    results, err := database.Search(params["query"].(string))
    if err != nil {
        return nil, ErrToolExecution.New(err).
            WithMCPCode(errific.MCPToolError).
            WithHelp("Database connection pool exhausted").
            WithSuggestion("Retry in 10 seconds or simplify your query").
            WithDocs("https://docs.example.com/tools/search_database").
            WithTags("database", "connection-pool", "retryable").
            WithRetryable(true).
            WithRetryAfter(10 * time.Second)
    }
    return results, nil
}

// Send MCP response to LLM
func SendMCPResponse(w http.ResponseWriter, err error) {
    response := map[string]interface{}{
        "jsonrpc": "2.0",
        "id":      "req-123",
        "error":   errific.ToMCPError(err),
    }
    json.NewEncoder(w).Encode(response)
}

LLM receives:

{
  "error": {
    "code": -32000,
    "message": "search_database tool failed",
    "data": {
      "help": "Database connection pool exhausted",
      "suggestion": "Retry in 10 seconds or simplify your query",
      "retryable": true,
      "retry_after": "10s"
    }
  }
}

LLM can now:

  • ✅ Explain error to user with help text
  • ✅ Take action based on suggestion
  • ✅ Check retryable to decide if retry is safe
  • ✅ Use retry_after for intelligent backoff
Scenario 5: RAG System Error Categorization

Problem: Need to categorize 10,000+ errors for ML training and search

Solution: Use semantic tags and labels for RAG-optimized error indexing

View Complete Example
// Use Case: RAG system with error categorization for semantic search
// Keywords: rag, semantic-search, vector-database, ml-training, error-categorization, embeddings

var ErrEmbedding errific.Err = "embedding generation failed"

// Create error with RAG metadata
func GenerateEmbedding(text string) ([]float64, error) {
    embedding, err := openai.CreateEmbedding(text)
    if err != nil {
        return nil, ErrEmbedding.New(err).
            WithTags("rag", "embedding", "openai", "rate-limit").
            WithLabel("model", "text-embedding-ada-002").
            WithLabel("provider", "openai").
            WithHelp("OpenAI API rate limit exceeded").
            WithContext(errific.Context{
                "token_count": len(text),
                "rate_limit":  "60/min",
            })
    }
    return embedding, nil
}

// Index errors for RAG search
func IndexErrorForRAG(err error) {
    vectorDB.Store(ErrorDocument{
        Tags:    errific.GetTags(err),     // ["rag", "embedding", "openai"]
        Labels:  errific.GetLabels(err),   // {"model": "...", "provider": "..."}
        Context: errific.GetContext(err),  // {"token_count": 1234, ...}
        Help:    errific.GetHelp(err),     // For similarity matching
    })
}

// Query similar errors
func QuerySimilarErrors(query string) []ErrorDocument {
    return vectorDB.SearchByTags([]string{"embedding", "rate-limit"})
}

Benefits:

  • ✅ Semantic tags enable error categorization
  • ✅ Labels provide structured filtering (provider, model)
  • ✅ Context contains numerical features for ML
  • ✅ Help text indexed for similarity search
  • ✅ Time-series analysis with timestamps

🤔 Decision Guide

Which Features Do I Need?
Start: I have an error
    │
    ├─ Need debugging info?           → Use .New() (automatic caller)
    ├─ Building an API?                → Use .WithHTTPStatus() + .WithCategory()
    ├─ Need retry logic?               → Use .WithRetryable() + .WithRetryAfter()
    ├─ Distributed system?             → Use .WithCorrelationID()
    ├─ MCP server for LLMs?            → Use .WithMCPCode() + .WithHelp()
    └─ RAG/ML system?                  → Use .WithTags() + .WithLabels()
Quick Reference Table
Feature Method When to Use Example Use Case
Automatic Caller .New() Always Debug which function failed
Error Codes .WithCode() Monitoring, alerts "Alert on ERR_DB_001"
Categories .WithCategory() Routing, HTTP mapping "Return 400 for validation errors"
Context Data .WithContext() Debugging, logging "What parameters caused this?"
Retry Logic .WithRetryable() Resilience, automation "AI agent auto-retry"
HTTP Status .WithHTTPStatus() API services "Auto-map to HTTP response"
MCP Codes .WithMCPCode() MCP servers "LLM-readable errors"
Recovery Help .WithHelp() AI self-healing "Guide automated recovery"
Correlation IDs .WithCorrelationID() Distributed tracing "Trace across services"
Semantic Tags .WithTags() RAG, search, ML "Categorize for training"
Labels .WithLabels() Filtering, grouping "Alert by severity"

📖 Documentation

Error Categories
// Use Case: Error categories for routing and HTTP status code mapping
// Keywords: categories, classification, http-mapping, error-routing

CategoryClient       // 4xx - client errors
CategoryServer       // 5xx - server errors
CategoryNetwork      // connectivity issues
CategoryValidation   // input validation
CategoryNotFound     // 404 errors
CategoryUnauthorized // 401/403 errors
CategoryTimeout      // timeout errors
Key Methods
// Use Case: Common error enrichment patterns and metadata extraction
// Keywords: methods, api-reference, error-enrichment, metadata-extraction

// Structured context
.WithContext(Context{"key": "value"})

// Machine-readable codes
.WithCode("ERR_001")
.WithCategory(CategoryServer)

// Retry automation
.WithRetryable(true)
.WithRetryAfter(5 * time.Second)
.WithMaxRetries(3)

// HTTP integration
.WithHTTPStatus(503)

// Extract metadata
GetCode(err)        // → "ERR_001"
GetCategory(err)    // → CategoryServer
IsRetryable(err)    // → true
GetHTTPStatus(err)  // → 503
GetContext(err)     // → Context map

🎯 Use Cases

  • API Services - Automatic HTTP status code mapping and JSON responses
  • Microservices - Structured logging with correlation IDs and context
  • Retry Logic - Built-in retry metadata for resilience patterns
  • AI Agents - Machine-readable error codes and categories for automation
  • Monitoring - JSON serialization for Datadog, ELK, Prometheus
  • Debugging - Automatic caller information and stack traces

📊 More Examples

Check out the comprehensive examples including:

  • Context attachment
  • Error codes and categories
  • Retry metadata
  • JSON serialization
  • AI agent scenarios
  • HTTP integration

Try it on the playground!

📚 RAG-Optimized Documentation

For AI agents and RAG systems, comprehensive documentation is available:

  • API Reference - Complete API documentation with examples, decision trees, and troubleshooting
  • Decision Guide - When to use each feature, error handling patterns, and automation guides
  • Docs Index - Documentation overview with semantic tags and FAQ

Each document is self-contained with full context for RAG retrieval.

📊 Coverage & Quality

  • 98.1% test coverage with 72+ test cases
  • 13 benchmarks for performance validation
  • 3 fuzz tests for robustness (315K+ executions, 0 crashes)
  • 5 integration tests for real-world scenarios
  • Thread-safe (race detector clean)
  • Zero external dependencies
  • Comprehensive examples and documentation

Documentation

Overview

Package errific provides enhanced error handling for Go with caller information, clean error wrapping, and helpful formatting methods.

errific simplifies error creation by adding runtime caller metadata (file, line, function) to errors, making debugging easier without sacrificing clean error messages. It supports error chaining, formatted messages, and configurable output options including stack traces.

Basic usage:

var ErrProcessThing errific.Err = "error processing thing"

func process() error {
    if err := validate(); err != nil {
        return ErrProcessThing.New(err)
    }
    return nil
}

The resulting error includes caller information:

error processing thing [mypackage/file.go:42.process]
validation failed [mypackage/validate.go:15.validate]

Configuration options include caller position (prefix/suffix/disabled), layout (newline/inline), stack traces, and path trimming.

Index

Constants

View Source
const (
	// Suffix adds caller information at the end of the error message.
	// This is default.
	Suffix callerOption = iota
	// Prefix adds caller information at the beginning of the error message.
	Prefix
	// Disabled does not include caller information in the error message.
	Disabled
)
View Source
const (
	// Newline joins errors with \n.
	// This is default.
	Newline layoutOption = iota
	// Inline wraps errors with ↩.
	Inline
)
View Source
const (
	// OutputPretty formats errors as human-readable multi-line text with all metadata.
	//
	// Example:
	//   user not found [main.go:20.GetUser]
	//     code: USER_404
	//     context: {user_id: user-123, source: database}
	//     http_status: 400
	OutputPretty outputFormatOption = iota

	// OutputJSON formats errors as compact JSON.
	// This is the default.
	// Useful for structured logging and machine processing.
	//
	// Example:
	//   {"error":"user not found","caller":"main.go:20","code":"USER_404",...}
	OutputJSON

	// OutputJSONPretty formats errors as indented JSON.
	// Useful for documentation, debugging, and human-readable JSON output.
	//
	// Example:
	//   {
	//     "error": "user not found",
	//     "code": "USER_404",
	//     "caller": "main.go:20"
	//   }
	OutputJSONPretty

	// OutputCompact formats errors as single-line text with key=value pairs.
	// Useful for log aggregation systems.
	//
	// Example:
	//   user not found [main.go:20] code=USER_404 user_id=user-123 http_status=400
	OutputCompact
)
View Source
const (
	// VerbosityMinimal shows only the error message and caller.
	//
	// Example:
	//   user not found [main.go:20.GetUser]
	VerbosityMinimal verbosityOption = iota

	// VerbosityStandard shows message, caller, code, category, and context.
	// Good balance for most applications.
	//
	// Example:
	//   user not found [main.go:20.GetUser]
	//     code: USER_404
	//     category: validation
	//     context: {user_id: user-123}
	VerbosityStandard

	// VerbosityFull shows all non-empty fields (default).
	// Recommended for debugging and development.
	//
	// Example:
	//   user not found [main.go:20.GetUser]
	//     code: USER_404
	//     category: validation
	//     context: {user_id: user-123, source: database}
	//     http_status: 400
	//     retryable: true
	//     correlation_id: trace-123
	//     help: Check if user exists
	VerbosityFull

	// VerbosityCustom allows fine-grained control via individual field flags.
	// Use with Show* and Hide* options.
	VerbosityCustom
)
View Source
const (
	// MCPParseError represents invalid JSON was received by the server.
	MCPParseError = -32700
	// MCPInvalidRequest represents the JSON sent is not a valid Request object.
	MCPInvalidRequest = -32600
	// MCPMethodNotFound represents the method does not exist / is not available.
	MCPMethodNotFound = -32601
	// MCPInvalidParams represents invalid method parameter(s).
	MCPInvalidParams = -32602
	// MCPInternalError represents internal JSON-RPC error.
	MCPInternalError = -32603
	// MCPToolError represents a tool execution error (custom range -32000 to -32099).
	MCPToolError = -32000
)

MCP error codes following JSON-RPC 2.0 specification. These codes enable errific errors to be serialized in MCP-compatible format for AI tool calling and Model Context Protocol integration.

Valid code ranges per JSON-RPC 2.0 specification:

  • Standard errors: -32768 to -32000 (reserved by JSON-RPC 2.0)
  • Server errors: -32000 to -32099 (available for application-specific errors)

When using WithMCPCode(), use the predefined constants below or custom codes in the -32000 to -32099 range for application-specific errors.

References:

View Source
const (
	// Trim current working directory from filenames.
	TrimCWD trimCWDOption = true
)
View Source
const (
	// Include stacktrace in error message.
	WithStack withStackTraceOption = true
)

Variables

View Source
var (
	// ShowCode includes error code in output.
	ShowCode = fieldVisibilityOption{/* contains filtered or unexported fields */}
	// HideCode excludes error code from output.
	HideCode = fieldVisibilityOption{/* contains filtered or unexported fields */}

	// ShowCategory includes error category in output.
	ShowCategory = fieldVisibilityOption{/* contains filtered or unexported fields */}
	// HideCategory excludes error category from output.
	HideCategory = fieldVisibilityOption{/* contains filtered or unexported fields */}

	// ShowContext includes structured context in output.
	ShowContext = fieldVisibilityOption{/* contains filtered or unexported fields */}
	// HideContext excludes structured context from output.
	HideContext = fieldVisibilityOption{/* contains filtered or unexported fields */}

	// ShowHTTPStatus includes HTTP status code in output.
	ShowHTTPStatus = fieldVisibilityOption{/* contains filtered or unexported fields */}
	// HideHTTPStatus excludes HTTP status code from output.
	HideHTTPStatus = fieldVisibilityOption{/* contains filtered or unexported fields */}

	// ShowRetryMetadata includes retry information (retryable, retry_after, max_retries) in output.
	ShowRetryMetadata = fieldVisibilityOption{/* contains filtered or unexported fields */}
	// HideRetryMetadata excludes retry information from output.
	HideRetryMetadata = fieldVisibilityOption{/* contains filtered or unexported fields */}

	// ShowMCPData includes MCP-related fields (correlation_id, help, suggestion, etc.) in output.
	ShowMCPData = fieldVisibilityOption{/* contains filtered or unexported fields */}
	// HideMCPData excludes MCP-related fields from output.
	HideMCPData = fieldVisibilityOption{/* contains filtered or unexported fields */}

	// ShowTags includes semantic tags in output.
	ShowTags = fieldVisibilityOption{/* contains filtered or unexported fields */}
	// HideTags excludes semantic tags from output.
	HideTags = fieldVisibilityOption{/* contains filtered or unexported fields */}

	// ShowLabels includes key-value labels in output.
	ShowLabels = fieldVisibilityOption{/* contains filtered or unexported fields */}
	// HideLabels excludes key-value labels from output.
	HideLabels = fieldVisibilityOption{/* contains filtered or unexported fields */}

	// ShowTimestamps includes timestamp and duration in output.
	ShowTimestamps = fieldVisibilityOption{/* contains filtered or unexported fields */}
	// HideTimestamps excludes timestamp and duration from output.
	HideTimestamps = fieldVisibilityOption{/* contains filtered or unexported fields */}
)
View Source
var (
	// TrimPrefixes from caller frame filenames.
	TrimPrefixes = func(prefixes ...string) trimPrefixesOption {
		return trimPrefixesOption{prefixes: prefixes}
	}
)

Functions

func Configure

func Configure(opts ...Option)

Configure errific options.

func GetCode

func GetCode(err error) string

GetCode extracts the error code from an error. Returns an empty string if the error doesn't have a code.

func GetCorrelationID

func GetCorrelationID(err error) string

GetCorrelationID extracts the correlation ID from an error. Returns an empty string if no correlation ID is set.

func GetDocs

func GetDocs(err error) string

GetDocs extracts the documentation URL from an error. Returns an empty string if no docs URL is set.

func GetDuration

func GetDuration(err error) time.Duration

GetDuration extracts the operation duration from an error. Returns 0 if no duration is set.

func GetHTTPStatus

func GetHTTPStatus(err error) int

GetHTTPStatus extracts the HTTP status code from an error. Returns 0 if no HTTP status is set.

func GetHelp

func GetHelp(err error) string

GetHelp extracts the help text from an error. Returns an empty string if no help text is set.

func GetLabel

func GetLabel(err error, key string) string

GetLabel extracts a specific label value from an error. Returns an empty string if the label doesn't exist.

func GetLabels

func GetLabels(err error) map[string]string

GetLabels extracts the labels from an error. Returns nil if no labels are set.

func GetMCPCode

func GetMCPCode(err error) int

GetMCPCode extracts the MCP error code from an error. Returns 0 if the error is nil or doesn't have an MCP code.

func GetMaxRetries

func GetMaxRetries(err error) int

GetMaxRetries extracts the maximum retry count from an error. Returns 0 if no max retries is set.

func GetRequestID

func GetRequestID(err error) string

GetRequestID extracts the request ID from an error. Returns an empty string if no request ID is set.

func GetRetryAfter

func GetRetryAfter(err error) time.Duration

GetRetryAfter extracts the suggested retry delay from an error. Returns 0 if no retry delay is set.

func GetSessionID

func GetSessionID(err error) string

GetSessionID extracts the session ID from an error. Returns an empty string if no session ID is set.

func GetSuggestion

func GetSuggestion(err error) string

GetSuggestion extracts the suggestion text from an error. Returns an empty string if no suggestion is set.

func GetTags

func GetTags(err error) []string

GetTags extracts the semantic tags from an error. Returns nil if no tags are set.

func GetTimestamp

func GetTimestamp(err error) time.Time

GetTimestamp extracts the timestamp from an error. Returns zero time if no timestamp is set.

func GetUserID

func GetUserID(err error) string

GetUserID extracts the user ID from an error. Returns an empty string if no user ID is set.

func IsRetryable

func IsRetryable(err error) bool

IsRetryable checks if an error is marked as retryable. Returns false if the error is not retryable or not an errific error.

Types

type Category

type Category string

Category represents the category of an error for automated handling.

const (
	// CategoryClient represents client-side errors (4xx).
	CategoryClient Category = "client"
	// CategoryServer represents server-side errors (5xx).
	CategoryServer Category = "server"
	// CategoryNetwork represents network connectivity errors.
	CategoryNetwork Category = "network"
	// CategoryValidation represents input validation errors.
	CategoryValidation Category = "validation"
	// CategoryNotFound represents resource not found errors (404).
	CategoryNotFound Category = "not_found"
	// CategoryUnauthorized represents authentication/authorization errors (401/403).
	CategoryUnauthorized Category = "unauthorized"
	// CategoryTimeout represents timeout errors.
	CategoryTimeout Category = "timeout"
)

func GetCategory

func GetCategory(err error) Category

GetCategory extracts the error category from an error. Returns an empty category if the error doesn't have one.

type Context

type Context map[string]any

Context is a map of key-value pairs that provides additional context for errors. This structured data can be used for debugging, logging, and automated error handling.

func GetContext

func GetContext(err error) Context

GetContext extracts structured context from an error. Returns nil if the error doesn't have context data. This function works with any error type but only extracts context from errific errors.

type Err

type Err string

Err string type.

To include runtime caller information on the error, one of the Err methods, other than Error(), must be called.

For examples see the example tests. All examples demonstrate using exported errors as a recommended best practice because exported errors enable unit-tests that assert expected errors such as: assert.ErrorIs(t, err, ErrProcessThing).

func (Err) Error

func (e Err) Error() string

func (Err) Errorf

func (e Err) Errorf(a ...any) errific

Errorf returns an error using Err formatted as text. Use Errorf if your Err string itself contains fmt format specifiers.

var ErrProcessThing errific.Err = "error processing thing id: '%s'"

return ErrProcessThing.Errorf("abc")

func (Err) New

func (e Err) New(errs ...error) errific

New returns an error using Err as text with errors joined.

var ErrProcessThing errific.Err = "error processing a thing"

return ErrProcessThing.New(err)

func (Err) WithCategory

func (e Err) WithCategory(category Category) errific

func (Err) WithCode

func (e Err) WithCode(code string) errific

func (Err) WithContext

func (e Err) WithContext(ctx Context) errific

func (Err) WithCorrelationID

func (e Err) WithCorrelationID(id string) errific

func (Err) WithDocs

func (e Err) WithDocs(url string) errific

func (Err) WithDuration

func (e Err) WithDuration(d time.Duration) errific

func (Err) WithHTTPStatus

func (e Err) WithHTTPStatus(status int) errific

func (Err) WithHelp

func (e Err) WithHelp(text string) errific

func (Err) WithLabel

func (e Err) WithLabel(key, value string) errific

func (Err) WithLabels

func (e Err) WithLabels(labels map[string]string) errific

func (Err) WithMCPCode

func (e Err) WithMCPCode(code int) errific

func (Err) WithMaxRetries

func (e Err) WithMaxRetries(max int) errific

func (Err) WithRequestID

func (e Err) WithRequestID(id string) errific

func (Err) WithRetryAfter

func (e Err) WithRetryAfter(duration time.Duration) errific

func (Err) WithRetryable

func (e Err) WithRetryable(retryable bool) errific

func (Err) WithSessionID

func (e Err) WithSessionID(id string) errific

func (Err) WithSuggestion

func (e Err) WithSuggestion(text string) errific

func (Err) WithTags

func (e Err) WithTags(tags ...string) errific

func (Err) WithTimestamp

func (e Err) WithTimestamp(t time.Time) errific

func (Err) WithUserID

func (e Err) WithUserID(id string) errific

func (Err) Withf

func (e Err) Withf(format string, a ...any) errific

Withf returns an error with a formatted string inline to Err as text.

var ErrProcessThing errific.Err = "error processing thing"

return ErrProcessThing.Withf("id: '%s'", "abc")

func (Err) Wrapf

func (e Err) Wrapf(format string, a ...any) errific

Wrapf return an error using Err as text and wraps a formatted error. Use Wrapf to format an error and wrap it.

var ErrProcessThing errific.Err = "error processing thing"

return ErrProcessThing.Wrapf("cause: %w", err)

type MCPError

type MCPError struct {
	Code    int             `json:"code"`
	Message string          `json:"message"`
	Data    json.RawMessage `json:"data,omitempty"`
}

MCPError represents a Model Context Protocol error in JSON-RPC 2.0 format. This format is compatible with MCP server error responses and AI tool calling protocols.

func ToMCPError

func ToMCPError(err error) MCPError

ToMCPError converts any error to MCP JSON-RPC 2.0 format. If the error is an errific error with an MCP code set, it uses that code. Otherwise, it defaults to MCPInternalError. Returns a zero MCPError if err is nil.

mcpErr := ToMCPError(err)
json.NewEncoder(w).Encode(mcpErr)

func (MCPError) Error

func (m MCPError) Error() string

Error implements the error interface for MCPError.

type Option

type Option interface {
	ErrificOption()
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL