Error Handling Protocol

Version: 1.0.0
Category: Error
Status: Stable


Overview

The Error Handling Protocol defines how AI agents should handle errors when interacting with Structs APIs. This includes error response formats, retry strategies, error recovery patterns, and best practices.

Key Principles:

  1. Always check for errors before processing responses
  2. Categorize errors by retryability and severity
  3. Implement retry logic for retryable errors
  4. Log all errors for debugging and monitoring
  5. Provide fallback behavior for non-retryable errors

Error Response Formats

Consensus Network API Error Response

Format:

{
  "code": 2,
  "message": "codespace structs code 1900: object not found",
  "details": []
}

Fields:

Example:

{
  "request": {
    "method": "GET",
    "url": "/structs/player/1-999",
    "headers": {
      "Accept": "application/json"
    }
  },
  "response": {
    "status": 400,
    "body": {
      "code": 2,
      "message": "codespace structs code 1900: object not found",
      "details": []
    }
  }
}

Web Application API Error Response

Format:

{
  "success": false,
  "data": null,
  "errors": [
    "Error message 1",
    "Error message 2"
  ]
}

Fields:

Example:

{
  "request": {
    "method": "GET",
    "url": "/api/player/999",
    "headers": {
      "Accept": "application/json"
    }
  },
  "response": {
    "status": 404,
    "body": {
      "success": false,
      "data": null,
      "errors": [
        "Player not found"
      ]
    }
  }
}

HTTP Status Codes

Standard HTTP Status Codes:


Error Categories

Error Code Schema

All error codes are defined in schemas/errors.md. Categories include:

  1. Success (code: 0): Operation successful
  2. Game Errors (codes: 1-9): Game-specific errors
  3. HTTP Errors (codes: 400, 404, 500): HTTP status codes
  4. Network Errors (timeout, network): Network-related errors

Retryable vs Non-Retryable Errors

Retryable Errors (can be retried):

Non-Retryable Errors (should not be retried):


Retry Strategies

Exponential Backoff

Recommended Strategy for retryable errors:

{
  "retryStrategy": {
    "type": "exponential",
    "maxRetries": 3,
    "initialDelay": 1000,
    "maxDelay": 10000,
    "backoffMultiplier": 2,
    "retryableErrors": ["1", "3", "4", "500", "timeout", "network"]
  }
}

Implementation Example:

{
  "retryLogic": {
    "attempt": 1,
    "delay": 1000,
    "maxRetries": 3,
    "backoff": {
      "attempt1": 1000,
      "attempt2": 2000,
      "attempt3": 4000
    }
  }
}

Fixed Delay Retry

Alternative Strategy for rate limiting:

{
  "retryStrategy": {
    "type": "fixed",
    "maxRetries": 3,
    "delay": 5000,
    "retryableErrors": ["429"]
  }
}

Rate Limit Handling

When receiving 429 Too Many Requests:

{
  "error": {
    "code": 429,
    "name": "RATE_LIMIT_EXCEEDED",
    "response": {
      "retry_after": 60
    },
    "handling": {
      "action": "wait",
      "waitTime": "response.retry_after",
      "retry": true
    }
  }
}

Strategy:

  1. Check Retry-After header or retry_after in response
  2. Wait for specified time
  3. Retry request
  4. If still rate limited, increase wait time

Error Recovery Patterns

Pattern 1: Resource Not Found

Error: ENTITY_NOT_FOUND (404) or codespace structs code 1900

Recovery:

{
  "error": "ENTITY_NOT_FOUND",
  "recovery": {
    "step1": "Verify entity ID format",
    "step2": "Check if entity exists (list endpoint)",
    "step3": "If doesn't exist, create or use alternative",
    "step4": "If format invalid, correct and retry"
  }
}

Example:

{
  "scenario": "Get player 1-999 (doesn't exist)",
  "error": {
    "code": 2,
    "message": "codespace structs code 1900: object not found"
  },
  "recovery": {
    "action": "List all players to find valid IDs",
    "fallback": "Use default player or create new"
  }
}

Pattern 2: Insufficient Resources

Error: INSUFFICIENT_FUNDS (code: 2) or INSUFFICIENT_CHARGE (code: 7)

Recovery:

{
  "error": "INSUFFICIENT_FUNDS",
  "recovery": {
    "step1": "Check current resources (query player/struct)",
    "step2": "Wait for resources to accumulate",
    "step3": "Monitor resource generation",
    "step4": "Retry when resources available"
  }
}

Example:

{
  "scenario": "Mining requires charge but struct has insufficient charge",
  "error": {
    "code": 7,
    "name": "INSUFFICIENT_CHARGE",
    "description": "Struct has insufficient charge"
  },
  "recovery": {
    "action": "Query struct charge level",
    "wait": "Monitor charge until sufficient",
    "retry": "Retry mining when charge >= required"
  }
}

Pattern 3: Player Halted

Error: PLAYER_HALTED (code: 6)

Recovery:

{
  "error": "PLAYER_HALTED",
  "recovery": {
    "step1": "Check player status (query player)",
    "step2": "Wait for player to come online",
    "step3": "Monitor player status",
    "step4": "Retry when player online"
  }
}

Example:

{
  "scenario": "Player is offline/halted",
  "error": {
    "code": 6,
    "name": "PLAYER_HALTED",
    "description": "Player is halted (offline)"
  },
  "recovery": {
    "action": "Query player status periodically",
    "wait": "Wait for player to come online",
    "retry": "Retry action when player.halted = false"
  }
}

Pattern 4: Network Errors

Error: NETWORK_ERROR or REQUEST_TIMEOUT

Recovery:

{
  "error": "NETWORK_ERROR",
  "recovery": {
    "step1": "Retry with exponential backoff",
    "step2": "Check network connectivity",
    "step3": "Verify endpoint availability",
    "step4": "Use alternative endpoint if available"
  }
}

Example:

{
  "scenario": "Network timeout during request",
  "error": {
    "code": "timeout",
    "name": "REQUEST_TIMEOUT"
  },
  "recovery": {
    "retry": {
      "attempt1": "Wait 1 second, retry",
      "attempt2": "Wait 2 seconds, retry",
      "attempt3": "Wait 4 seconds, retry"
    },
    "fallback": "Log error and abort if all retries fail"
  }
}

Error Handling Best Practices

1. Always Check for Errors

Pattern:

{
  "responseHandling": {
    "step1": "Check HTTP status code",
    "step2": "Check response body for error fields",
    "step3": "Categorize error (retryable vs non-retryable)",
    "step4": "Apply appropriate handling strategy"
  }
}

2. Log All Errors

Pattern:

{
  "errorLogging": {
    "include": [
      "error code",
      "error message",
      "request details (method, URL, params)",
      "response details",
      "timestamp",
      "retry attempt (if applicable)"
    ]
  }
}

3. Implement Circuit Breaker

Pattern for repeated failures:

{
  "circuitBreaker": {
    "failureThreshold": 5,
    "timeout": 60000,
    "halfOpenRetries": 1,
    "states": ["closed", "open", "half-open"]
  }
}

Strategy:

4. Provide Fallback Behavior

Pattern:

{
  "fallback": {
    "nonRetryableError": "Use cached data or default values",
    "retryableError": "Retry with backoff",
    "criticalError": "Abort operation and notify"
  }
}

5. Validate Before Retry

Pattern:

{
  "retryValidation": {
    "step1": "Verify error is retryable",
    "step2": "Check retry count < max retries",
    "step3": "Validate request parameters unchanged",
    "step4": "Apply backoff delay",
    "step5": "Retry request"
  }
}

Error Code Reference

Complete error code catalog: See schemas/errors.md

Quick Reference:


Examples

Example 1: Handling Entity Not Found

{
  "scenario": "Get player that doesn't exist",
  "request": {
    "method": "GET",
    "url": "/structs/player/1-999"
  },
  "response": {
    "status": 400,
    "body": {
      "code": 2,
      "message": "codespace structs code 1900: object not found"
    }
  },
  "handling": {
    "errorCode": 2,
    "category": "notRetryable",
    "action": "Verify player ID exists",
    "recovery": {
      "step1": "List all players to find valid IDs",
      "step2": "Use valid player ID or create new player"
    }
  }
}

Example 2: Handling Rate Limit

{
  "scenario": "Rate limit exceeded",
  "request": {
    "method": "GET",
    "url": "/structs/player"
  },
  "response": {
    "status": 429,
    "headers": {
      "Retry-After": "60"
    },
    "body": {
      "error": "Rate limit exceeded",
      "code": 429,
      "retry_after": 60
    }
  },
  "handling": {
    "errorCode": 429,
    "category": "retryable",
    "action": "Wait and retry",
    "recovery": {
      "waitTime": 60,
      "retry": true,
      "strategy": "fixed delay"
    }
  }
}

Example 3: Handling Network Error with Retry

{
  "scenario": "Network timeout",
  "request": {
    "method": "GET",
    "url": "/structs/player/1-1"
  },
  "error": {
    "code": "timeout",
    "name": "REQUEST_TIMEOUT"
  },
  "handling": {
    "errorCode": "timeout",
    "category": "retryable",
    "action": "Retry with exponential backoff",
    "recovery": {
      "attempt1": {
        "delay": 1000,
        "retry": true
      },
      "attempt2": {
        "delay": 2000,
        "retry": true
      },
      "attempt3": {
        "delay": 4000,
        "retry": true
      },
      "maxRetries": 3,
      "fallback": "Log error and abort if all retries fail"
    }
  }
}

Integration with Other Protocols

Query Protocol Integration

When querying, always check for errors:

{
  "queryPattern": {
    "request": "GET /structs/player/{id}",
    "errorHandling": {
      "checkStatus": true,
      "checkBody": true,
      "categorizeError": true,
      "applyRecovery": true
    }
  }
}

Action Protocol Integration

When performing actions, handle errors appropriately:

{
  "actionPattern": {
    "request": "POST /cosmos/tx/v1beta1/txs",
    "errorHandling": {
      "transactionErrors": {
        "INSUFFICIENT_FUNDS": "Wait for resources",
        "INVALID_SIGNATURE": "Re-sign and retry",
        "PLAYER_HALTED": "Wait for player online"
      }
    }
  }
}

Testing Error Handling

Test Cases

  1. Entity Not Found: Request non-existent entity
  2. Rate Limiting: Make too many requests
  3. Network Errors: Simulate network failures
  4. Invalid Requests: Send malformed requests
  5. Resource Errors: Attempt actions without sufficient resources

Validation


References


Last Updated: January 2025