Version: 1.0.0
Category: Error
Status: Stable
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:
Format:
{
"code": 2,
"message": "codespace structs code 1900: object not found",
"details": []
}
Fields:
code (number): Error code (2 = not found)message (string): Human-readable error message with codespace and error codedetails (array): Additional error details (may be empty)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": []
}
}
}
Format:
{
"success": false,
"data": null,
"errors": [
"Error message 1",
"Error message 2"
]
}
Fields:
success (boolean): Always false for errorsdata (null): No data on errorerrors (array): Array of error messagesExample:
{
"request": {
"method": "GET",
"url": "/api/player/999",
"headers": {
"Accept": "application/json"
}
},
"response": {
"status": 404,
"body": {
"success": false,
"data": null,
"errors": [
"Player not found"
]
}
}
}
Standard HTTP Status Codes:
200 - Success400 - Bad Request (invalid request format)404 - Not Found (resource doesn’t exist)429 - Too Many Requests (rate limit exceeded)500 - Internal Server Error (server error)503 - Service Unavailable (service temporarily unavailable)All error codes are defined in schemas/errors.md. Categories include:
code: 0): Operation successfulcodes: 1-9): Game-specific errorscodes: 400, 404, 500): HTTP status codestimeout, network): Network-related errorsRetryable Errors (can be retried):
GENERAL_ERROR (code: 1)INVALID_SIGNATURE (code: 3)INSUFFICIENT_GAS (code: 4)INTERNAL_SERVER_ERROR (code: 500)REQUEST_TIMEOUT (timeout)NETWORK_ERROR (network)Non-Retryable Errors (should not be retried):
INSUFFICIENT_FUNDS (code: 2)INVALID_MESSAGE (code: 5)PLAYER_HALTED (code: 6)INSUFFICIENT_CHARGE (code: 7)INVALID_LOCATION (code: 8)INVALID_TARGET (code: 9)ENTITY_NOT_FOUND (code: 404)BAD_REQUEST (code: 400)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
}
}
}
Alternative Strategy for rate limiting:
{
"retryStrategy": {
"type": "fixed",
"maxRetries": 3,
"delay": 5000,
"retryableErrors": ["429"]
}
}
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:
Retry-After header or retry_after in responseError: 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"
}
}
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"
}
}
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"
}
}
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"
}
}
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"
}
}
Pattern:
{
"errorLogging": {
"include": [
"error code",
"error message",
"request details (method, URL, params)",
"response details",
"timestamp",
"retry attempt (if applicable)"
]
}
}
Pattern for repeated failures:
{
"circuitBreaker": {
"failureThreshold": 5,
"timeout": 60000,
"halfOpenRetries": 1,
"states": ["closed", "open", "half-open"]
}
}
Strategy:
Pattern:
{
"fallback": {
"nonRetryableError": "Use cached data or default values",
"retryableError": "Retry with backoff",
"criticalError": "Abort operation and notify"
}
}
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"
}
}
Complete error code catalog: See schemas/errors.md
Quick Reference:
0 - SUCCESS1 - GENERAL_ERROR (retryable)2 - INSUFFICIENT_FUNDS (not retryable)3 - INVALID_SIGNATURE (retryable)4 - INSUFFICIENT_GAS (retryable)5 - INVALID_MESSAGE (not retryable)6 - PLAYER_HALTED (not retryable)7 - INSUFFICIENT_CHARGE (not retryable)8 - INVALID_LOCATION (not retryable)9 - INVALID_TARGET (not retryable)400 - BAD_REQUEST (not retryable)404 - ENTITY_NOT_FOUND (not retryable)429 - RATE_LIMIT_EXCEEDED (retryable with delay)500 - INTERNAL_SERVER_ERROR (retryable)timeout - REQUEST_TIMEOUT (retryable)network - NETWORK_ERROR (retryable){
"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"
}
}
}
{
"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"
}
}
}
{
"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"
}
}
}
When querying, always check for errors:
{
"queryPattern": {
"request": "GET /structs/player/{id}",
"errorHandling": {
"checkStatus": true,
"checkBody": true,
"categorizeError": true,
"applyRecovery": true
}
}
}
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"
}
}
}
}
schemas/errors.mdschemas/responses.mdprotocols/query-protocol.mdprotocols/action-protocol.mdtechnical/api-reference.md#error-handlingLast Updated: January 2025