5.9 KiB
name, description
| name | description |
|---|---|
| retry-on-fail | Automatically stop executing any operation if the failure retry count exceeds 5 times. Use when Codex needs to perform repeated operations with automatic backoff and fail-safe behavior, such as network requests, file operations, or API calls that may temporarily fail. |
Retry on Fail
This skill provides guidance for implementing automatic retry logic with a maximum of 5 attempts before stopping execution.
About the Skill
The retry-on-fail skill ensures robust operation by automatically retrying failed actions up to 5 times, then halting execution if all retries are exhausted. This prevents infinite loops and helps identify persistent failures that need manual intervention.
When to Use This Skill
Use this skill when:
- Performing network requests (HTTP calls, DNS lookups)
- Executing file operations that may fail temporarily (write, read, delete)
- Making API calls with potential rate limits or timeouts
- Running commands in shell environments where transient errors occur
- Any operation where temporary failures are expected but persistent failures should stop execution
Retry Behavior
- Maximum attempts: 5 retries total (including the initial attempt = 6 total tries)
- Backoff strategy: Exponential backoff with increasing delays between retries
- Failure detection: Based on error codes, HTTP status codes >= 400, or non-zero exit codes
- Stopping condition: After 5 failed attempts, execution stops and an error is reported
Core Principles
Concise is Key
The retry logic should be minimal and focused. Include only the essential code for:
- Attempting the operation
- Checking if it succeeded
- Implementing backoff delay
- Counting failures
- Stopping after 5 attempts
Set Appropriate Degrees of Freedom
Use a fixed maximum retry count (5) for consistency across all operations. This provides predictable behavior and makes debugging easier when persistent failures occur.
Anatomy of a Skill
Every skill consists of a required SKILL.md file:
retry-on-fail/
└── SKILL.md (required)
├── YAML frontmatter metadata (required)
│ ├── name: retry-on-fail
│ └── description: [as above]
└── Markdown instructions (required)
Skill Implementation Pattern
Retry Logic Structure
The core retry mechanism follows this pattern:
- Initialize: Set
attempt_count = 0,max_attempts = 5 - Loop: While
attempt_count < max_attempts:- Increment attempt counter
- Execute the operation
- If successful, return immediately
- If failed, apply backoff delay and continue
- Exhausted: After all attempts fail, raise exception or return error
Backoff Strategy
Use exponential backoff with the following delays:
- Attempt 1: Immediate (0s)
- Attempt 2: 1 second
- Attempt 3: 2 seconds
- Attempt 4: 4 seconds
- Attempt 5: 8 seconds
Total delay between attempts increases exponentially to avoid overwhelming the target system.
Error Handling
- Success: Return immediately on first success
- Transient failure: Retry with backoff
- Persistent failure: After 5 attempts, stop and report error with full context
Usage Examples
Network Request Example
def fetch_with_retry(url):
"""Fetch URL with retry logic"""
for attempt in range(6): # Initial + 5 retries
attempt_count += 1
try:
response = requests.get(url, timeout=10)
if response.status_code < 400:
return response.json()
except Exception as e:
pass
# Apply backoff (exponential)
delay = min(2 ** attempt, 8)
time.sleep(delay)
raise RetryExhausted(f"Failed after {attempt_count} attempts")
File Operation Example
def write_file_with_retry(filepath, content):
"""Write file with retry logic"""
for attempt in range(6):
attempt_count += 1
try:
with open(filepath, 'w') as f:
f.write(content)
return True
except Exception as e:
pass
# Apply backoff
delay = min(2 ** attempt, 8)
time.sleep(delay)
raise RetryExhausted(f"Failed to write file after {attempt_count} attempts")
Shell Command Example
def run_command_with_retry(cmd):
"""Run shell command with retry logic"""
for attempt in range(6):
attempt_count += 1
try:
result = subprocess.run(cmd, capture_output=True, timeout=30)
if result.returncode == 0:
return True
except Exception as e:
pass
# Apply backoff
delay = min(2 ** attempt, 8)
time.sleep(delay)
raise RetryExhausted(f"Command failed after {attempt_count} attempts")
Best Practices
- Always track attempts: Log the number of attempts made for debugging
- Use meaningful delays: Exponential backoff prevents overwhelming targets
- Provide context on failure: When stopping, include the last error and attempt count
- Consider retryable errors: Only retry transient failures (network, timeout), not permanent ones (404, 500)
- Set appropriate timeouts: Each individual operation should have its own timeout
Common Pitfalls to Avoid
- Infinite loops: Always ensure a maximum attempt count is enforced
- No backoff: Linear delays can overwhelm systems; use exponential instead
- Ignoring error types: Not all errors are retryable (e.g., 404 vs. connection error)
- Missing context: Don't forget to log what failed and how many times
Testing the Skill
Test the skill with:
- Transient failures: Simulate network issues that resolve after retries
- Persistent failures: Ensure it stops after 5 attempts
- Success on first try: Verify it returns immediately without retrying
- Edge cases: Test at exactly 5th attempt, varying delays