Skip to course content
Free generative AI app course

Generative AI Application Development with Python

Unit 09.00: The four ways a call fails

Four ways a call fails, and half of them are made worse by retrying.

Retryable and not

Six failure modes with a verdict each.

The code sorts them.

FAILURES = [
    ("429 rate limited", True,  "wait and retry"),
    ("500 server error", True,  "retry a bounded number of times"),
    ("timeout",          True,  "retry -- but it may already have succeeded"),
    ("400 bad request",  False, "your payload is wrong; retrying repeats it"),
    ("401 unauthorised", False, "the key is wrong; retrying repeats it"),
    ("content filtered", False, "retrying the same prompt gets the same result"),
]
print(f"{'failure':20} {'retryable':>10}  action")
for name, retryable, action in FAILURES:
    print(f"{name:20} {str(retryable):>10}  {action}")

retryable = sum(1 for _, r, _ in FAILURES if r)
print(f"\n{retryable} of {len(FAILURES)} are worth retrying")

# Retrying a 400 costs three times as much and delays the error by three
# attempts. Classify before looping -- the distinction is whether anything
# could plausibly differ next time.

A 400 or a 401 will fail identically three times, costing three times as much and delaying the real error by three attempts. Content filtering is the same: the same prompt gets the same result.

The distinction is simply whether anything could plausibly differ next time. Rate limits and transient server errors qualify; a malformed payload does not.

The mistake this prevents

The mistake is a blanket retry on any exception. It is one line, it looks robust, and it triples your cost on exactly the failures where the extra attempts are guaranteed to fail.

Takeaway

Classify failures before retrying. Retry only where something could plausibly differ next time; a 400 retried three times is three times the cost and a delayed error.