Skip to content
skyl

Handling Failure

Classified errors, jittered backoff, and knowing what never to retry.

skyl classifies every provider failure onto one of eight sentinels, retries the three that are worth retrying, and never retries the five that are not. This chapter is about branching on that classification instead of on message text.

In this chapter

  • The eight sentinel errors and what each means
  • How *skyl.Error carries the detail, and how to reach it
  • How backoff works, and why jitter is not optional
  • The difference between a per-attempt timeout and your own deadline
  • What a rate limit means after skyl has already retried
  • Why refusals and auth failures are never retried

Branch on classification#

goCompiles
resp, err := client.Complete(ctx, req)
switch {
case err == nil:
	// ok
case errors.Is(err, skyl.ErrRateLimit):
	// skyl already retried with backoff; this means it kept failing.
case errors.Is(err, skyl.ErrAuth):
	log.Fatal("bad API key")
case errors.Is(err, skyl.ErrNotFound):
	log.Fatal("no such model for this provider")
}
resp, err := client.Complete(ctx, req)
switch {
case err == nil:
	// ok
case errors.Is(err, skyl.ErrRateLimit):
	// skyl already retried with backoff; this means it kept failing.
case errors.Is(err, skyl.ErrAuth):
	log.Fatal("bad API key")
case errors.Is(err, skyl.ErrNotFound):
	log.Fatal("no such model for this provider")
}

Never match on message text. Providers reword their messages, and string matching breaks silently when they do.

SentinelMessageRetried?Meaning
ErrAuthskyl: authentication failedNeverThe credential was missing, malformed, or rejected. The same key will fail again.
ErrRateLimitskyl: rate limitedYesThe provider is throttling. Retried with backoff, honouring Retry-After.
ErrNotFoundskyl: not foundNeverThe model or endpoint does not exist for this account. Because model IDs pass through unvalidated, a typo arrives here rather than failing locally.
ErrBadRequestskyl: invalid requestNeverThe request was malformed. Often produced locally by Request.Validate.
ErrServerskyl: provider server errorYesThe provider failed on its side. Retried with backoff.
ErrUnsupportedskyl: unsupported by this providerNeverThis provider cannot express part of the request. Returned instead of silently dropping data, because a quietly discarded image looks like a model that ignored the question.
ErrRefusalskyl: model declined the requestNeverThe model or its safety classifiers declined. The same prompt gets the same answer.
ErrStreamClosedskyl: stream is closedNeverThe stream was used after being closed.

Read Error Classification for *skyl.Error, errors.As, and how HTTP statuses map onto sentinels.

Read more →

Retries#

Read Retries and Backoff for the exact delay formula and why full jitter matters at fleet scale.

Read more →

Timeouts#

Read Timeouts and CancellationWithTimeout bounds an attempt, your context bounds the call.

Read more →

Rate limits#

Read Rate Limits and Retry-After for why Retry-After has its own cap, separate from the backoff ceiling.

Read more →

Refusals#

Read Refusals — a refusal reaches you two different ways depending on whether it carried text.

Read more →

What is never retried#

Read What Is Never Retried for the five sentinels skyl refuses to retry, and the one surprising case.

Read more →

What’s next?

Start with Error Classification. If you are debugging a specific failure right now, the sentinel table above will tell you which page to jump to.

Edit this page on GitHub