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

Every webapp (structs-webapp) JSON response — success or failure — uses the same ApiResponseContentDto envelope. On failure the HTTP status is 400 (bad request / validation), 401 (unauthenticated or signature failure), 403, 404, or 409, success is false, and errors is a keyed object (NOT an array).

Format:

{
  "success": false,
  "errors": {
    "signature_validation_failed": "Invalid signature"
  },
  "data": null
}

Fields:

Example (validation failure on a catalog read with a missing required param):

{
  "request": {
    "method": "GET",
    "url": "/api/stat/power/object/1-11/range/page/1",
    "headers": {
      "Accept": "application/json"
    }
  },
  "response": {
    "status": 400,
    "body": {
      "success": false,
      "errors": {
        "start_time_end_time_required": "start_time and end_time query params are required (unix seconds)"
      },
      "data": null
    }
  }
}

Parsing rule: always check success first, then read errors (keyed object) or unwrap data. Never assume a top-level error/code/details body for webapp responses — that shape is only used by the consensus network API above.

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": "Action requires charge but the player's shared charge bar is too low",
  "error": {
    "code": 7,
    "name": "INSUFFICIENT_CHARGE",
    "description": "Player has insufficient charge (charge is per-player, not per-struct)"
  },
  "recovery": {
    "action": "Query player charge level (CurrentBlockHeight - player.lastActionBlock)",
    "wait": "Monitor charge until sufficient",
    "retry": "Retry the action 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