REQ-C-014: Error Responses Include retryable and retry_after_ms
Tier: Command Contract | Priority: P1
Source: §19 Retry Hints in Error Responses
Addresses: Severity: High / Token Spend: High / Time: High / Context: Medium
Description
Every error response MUST include error.retryable (boolean or the string "maybe") indicating whether the same invocation with identical arguments is safe to retry. For retryable errors, the response SHOULD include error.retry_after_ms (integer milliseconds to wait before retrying) and error.retry_strategy (one of: "immediate", "linear_backoff", "exponential_backoff"). The framework MUST maintain a default retryable value for each error code in its error registry, which commands inherit unless overridden.
Acceptance Criteria
- Every error response includes
error.retryable - A
RATE_LIMITEDerror includeserror.retry_after_ms > 0 - A
VALIDATION_ERRORerror haserror.retryable: false - A
TIMEOUTerror haserror.retryable: true - The framework error registry maps all standard error codes to default
retryablevalues
Schema
Types: response-envelope.md
This requirement extends ResponseEnvelope.ErrorDetail with the following required/recommended fields:
| Field | Type | Required | Description |
|---|---|---|---|
error.retryable |
boolean | "maybe" |
yes | Whether the identical invocation is safe to retry |
error.retry_after_ms |
integer | when retryable: true |
Milliseconds the agent should wait before retrying |
error.retry_strategy |
"immediate" | "linear_backoff" | "exponential_backoff" |
recommended | Backoff strategy to apply |
Wire Format
$ tool deploy --target prod
{
"ok": false,
"data": null,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "API rate limit reached — too many requests in the last 60 seconds",
"retryable": true,
"retry_after_ms": 30000,
"retry_strategy": "exponential_backoff"
},
"warnings": [],
"meta": { "duration_ms": 8 }
}
Timeout error (retryable, no delay):
{
"ok": false,
"data": null,
"error": {
"code": "OPERATION_TIMEOUT",
"message": "Command exceeded the 30 s timeout",
"retryable": true,
"retry_after_ms": 0,
"retry_strategy": "immediate"
},
"warnings": [],
"meta": { "duration_ms": 30001 }
}
Validation error (not retryable):
{
"ok": false,
"data": null,
"error": {
"code": "INVALID_ENVIRONMENT",
"message": "Unknown target 'prodution'",
"retryable": false,
"phase": "validation",
"suggestion": "Valid values: prod, staging, dev"
},
"warnings": [],
"meta": { "duration_ms": 3 }
}
Example
The command author overrides the framework default retryable value and supplies retry guidance at registration time:
register command "deploy":
exit_codes:
SUCCESS (0): retryable: false, side_effects: complete
TIMEOUT (10): retryable: true, side_effects: partial,
retry_after_ms: 0, retry_strategy: immediate
RATE_LIMITED(11): retryable: true, side_effects: none,
retry_after_ms: 30000, retry_strategy: exponential_backoff
ARG_ERROR(3): retryable: false, side_effects: none
Related
| Requirement | Tier | Relationship |
|---|---|---|
| REQ-C-013 | C | Extends: adds retryable and retry_after_ms to the error object defined there |
| REQ-C-001 | C | Sources: retryable default for each error code comes from the exit code declaration |
| REQ-F-001 | F | Provides: standard TIMEOUT and RATE_LIMITED codes whose default retryable values this requirement governs |
| REQ-F-004 | F | Wraps: error.retryable and error.retry_after_ms are fields within ResponseEnvelope.ErrorDetail |