Skip to content

Feature Request: Standardized Error Code System and Enhanced Error Context #25554

@hinokamikagura

Description

@hinokamikagura

Summary

The Cosmos SDK currently lacks a standardized error code system and consistent error context propagation, making it difficult for developers to programmatically handle errors, build better error messages for end users, and debug issues across modules. This proposal introduces a unified error code registry and enhanced error context system.

Type

  • Feature Request
  • Bug Report
  • Documentation Improvement

Description

Current Behavior

When errors occur in Cosmos SDK modules, they are typically returned as simple error strings or wrapped errors without:

  • Standardized error codes that can be programmatically checked
  • Consistent error context (module name, transaction context, state information)
  • Error categorization (validation, state, permission, etc.)
  • Links to relevant documentation
  • Suggested remediation steps

Example of current error handling:

// Current approach - minimal context
return sdkerrors.Wrap(sdkerrors.ErrInsufficientFunds, "insufficient balance")
// Results in: "insufficient balance: insufficient funds"

Expected Behavior

A standardized error system that provides:

  1. Error Codes: Unique, hierarchical error codes (e.g., BANK_001, STAKING_042)
  2. Rich Context: Module name, transaction hash, block height, account addresses, etc.
  3. Error Categories: Validation, State, Permission, Configuration, etc.
  4. Documentation Links: Direct links to relevant docs
  5. Programmatic Access: Easy to check error types in code

Example of improved error:

// Proposed approach - rich context
return sdkerrors.New(
    sdkerrors.CodeBankInsufficientFunds, // BANK_001
    "Insufficient funds for transaction",
    sdkerrors.WithModule("bank"),
    sdkerrors.WithAccount(accountAddr),
    sdkerrors.WithAmount(required, available),
    sdkerrors.WithTxHash(txHash),
    sdkerrors.WithDocLink("/modules/bank#insufficient-funds"),
)

Motivation

As a Senior Web3 Backend Developer who has built 13+ production blockchain applications, I've encountered several pain points:

  1. Difficult Error Handling: Without error codes, we can't programmatically handle specific error cases
  2. Poor User Experience: Generic error messages don't help end users understand what went wrong
  3. Debugging Challenges: Lack of context makes it hard to trace errors across module boundaries
  4. Integration Issues: Building APIs or frontends that need to handle Cosmos SDK errors requires string matching, which is fragile

Real-world impact:

  • When building DeFi platforms, we need to show user-friendly error messages
  • Trading bots need to handle specific error cases differently
  • API services need to return structured error responses
  • Debugging production issues requires more context than currently available

Proposed Solution

1. Error Code Registry System

Create a centralized error code registry in cosmos-sdk/errors:

// errors/codes.go
const (
    // Bank module errors (BANK_001 - BANK_099)
    CodeBankInsufficientFunds     = "BANK_001"
    CodeBankInvalidAmount          = "BANK_002"
    CodeBankInvalidAddress         = "BANK_003"
    
    // Staking module errors (STAKING_001 - STAKING_099)
    CodeStakingInsufficientDelegation = "STAKING_001"
    
    // ... other modules
)

// Error categories
type ErrorCategory string

const (
    CategoryValidation   ErrorCategory = "validation"
    CategoryState        ErrorCategory = "state"
    CategoryPermission   ErrorCategory = "permission"
    CategoryConfiguration ErrorCategory = "configuration"
)

2. Enhanced Error Type

// errors/error.go
type SDKError struct {
    Code        string
    Category    ErrorCategory
    Module      string
    Message     string
    Context     map[string]interface{}
    DocLink     string
    SuggestedFix string
    Wrapped     error
}

func (e *SDKError) Error() string {
    // Format error message with context
}

func (e *SDKError) Code() string {
    return e.Code
}

func (e *SDKError) IsCode(code string) bool {
    return e.Code == code
}

3. Helper Functions

// errors/helpers.go
func New(code, message string, opts ...ErrorOption) *SDKError {
    // Create new error with options
}

func WithModule(module string) ErrorOption
func WithAccount(addr sdk.AccAddress) ErrorOption
func WithAmount(required, available sdk.Coin) ErrorOption
func WithTxHash(hash []byte) ErrorOption
func WithDocLink(link string) ErrorOption
func WithSuggestedFix(fix string) ErrorOption

4. Backward Compatibility

Ensure backward compatibility by:

  • Keeping existing sdkerrors functions working
  • Providing migration path for existing code
  • Adding deprecation warnings for old patterns

Use Cases

Use Case 1: Programmatic Error Handling

// In a DeFi application
err := bankKeeper.SendCoins(ctx, from, to, amount)
if err != nil {
    var sdkErr *sdkerrors.SDKError
    if errors.As(err, &sdkErr) {
        switch sdkErr.Code() {
        case sdkerrors.CodeBankInsufficientFunds:
            // Show user-friendly message with available balance
            return fmt.Sprintf("Insufficient balance. Available: %s", 
                sdkErr.Context["available"])
        case sdkerrors.CodeBankInvalidAddress:
            return "Invalid recipient address"
        }
    }
}

Use Case 2: API Error Responses

// In REST API handler
if err != nil {
    var sdkErr *sdkerrors.SDKError
    if errors.As(err, &sdkErr) {
        return JSONResponse{
            Error: sdkErr.Code(),
            Message: sdkErr.Message,
            Context: sdkErr.Context,
            DocLink: sdkErr.DocLink,
        }
    }
}

Use Case 3: Frontend Error Display

// In frontend application
if (error.code === 'BANK_001') {
    showError(`Insufficient funds. You need ${error.context.required} but only have ${error.context.available}`);
    showLink(error.docLink); // Link to documentation
}

Implementation Plan

Phase 1: Core Infrastructure

  1. Create cosmos-sdk/errors package with error code registry
  2. Implement SDKError type with context support
  3. Add helper functions for creating errors
  4. Write comprehensive tests

Phase 2: Module Migration

  1. Migrate bank module to use new error system
  2. Migrate staking module
  3. Create migration guide for other modules
  4. Update documentation

Phase 3: Developer Tools

  1. Add error code validation in CI/CD
  2. Create error code generator tool
  3. Add error documentation generator
  4. Create migration tool for existing code

Benefits

  • Better Developer Experience: Clear, actionable error messages
  • Improved User Experience: End users get helpful error messages
  • Easier Integration: APIs and frontends can handle errors programmatically
  • Better Debugging: Rich context helps identify issues faster
  • Documentation: Error codes link to relevant documentation
  • Consistency: Standardized approach across all modules

Related Issues

This addresses concerns mentioned in:

  • General developer experience discussions
  • Error handling in module development
  • API integration challenges

Additional Context

Based on my experience building production Web3 applications:

  • ChainPro: Needed better error handling for trading operations
  • FeeFree DEX: Required user-friendly error messages for failed transactions
  • Trading Bots: Needed programmatic error handling for different failure modes

This improvement would significantly enhance the developer experience and make Cosmos SDK more accessible to developers building production applications.

Open Questions

  1. Should error codes be hierarchical (e.g., BANK_001_01 for sub-errors)?
  2. How should we handle error code conflicts across modules?
  3. Should error context be limited in size to avoid performance issues?
  4. How do we ensure error codes remain stable across SDK versions?

Contribution

I'm willing to contribute to this effort by:

  • Implementing the core error system
  • Migrating one or more modules as a reference implementation
  • Writing documentation and migration guides
  • Creating developer tools for error code management

Checklist

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions