Python SDK

Python SDK - Error Handling

Handle SkytellsError, retry transient failures, and write resilient Python code with the Skytells SDK.

Every error thrown by the Skytells Python SDK is a SkytellsError. Catch it once and branch on the error_id to respond correctly — whether that's retrying, notifying the user, or logging for debugging.

For the complete list of error codes and HTTP statuses, see the Errors reference.


SkytellsError

All SDK errors are instances of SkytellsError. It carries structured metadata so you can branch on machine-readable fields rather than message strings.

Properties

error_idstr | None

Machine-readable error identifier (e.g. "UNAUTHORIZED", "MODEL_NOT_FOUND"). Always check this field when branching.

messagestr

Human-readable description of the error. Do not use in code logic.

status_codeint | None

HTTP status code from the API response, or None for client-side errors.

responsedict | None

Full raw response body from the server, if available.

Catching errors

Basic
from skytells import SkytellsClient, SkytellsError

client = SkytellsClient()

try:
  prediction = client.run("truefusion-pro", input={
      "prompt": "A futuristic city at dusk",
  })
  print(prediction.outputs())
except SkytellsError as e:
  print(f"Error [{e.error_id}]: {e.message}")
  print(f"HTTP status: {e.status_code}")

Python SDK Error Reference

Since the Python SDK is a wrapper around the API, the error handling is the same as the API.

For the complete list of error codes and HTTP statuses, see the Errors reference.

Client-side errors

While the API can return client-side errors, the Python SDK will handle them automatically. These errors are raised by the SDK itself, not by the API server.

Error IDDescriptionResolution
PREDICTION_FAILEDThe prediction completed with a "failed" status. Raised by run() and wait() when inference fails.Retry the prediction or notify the user.
WAIT_TIMEOUTwait() exceeded its max_wait limit without the prediction completing. The prediction is still running — cancel it or poll manually.Cancel the prediction or poll manually.
REQUEST_TIMEOUTThe HTTP request exceeded the client timeout. Increase timeout in ClientOptions or retry.Increase the timeout or retry the request.
NETWORK_ERRORNetwork-level failure — no HTTP response received. Check connectivity and retry.Check connectivity and retry.
SERVER_ERRORNon-JSON or unexpected response from the server. Usually transient — retry with backoff.Retry with backoff.
INVALID_JSONResponse body could not be parsed as JSON. Report this to support.Report this to support.

Retry Configuration

Configure automatic retries on the client. By default, retries are disabled (retries=0).

The SDK uses linear backoff: retry attempt n waits retry_delay * n milliseconds before the next attempt.

Default retry_on status codes: 429, 500, 502, 503, 504.

RetryOptions

Simple
from skytells import SkytellsClient

# Retry up to 3 times on 429 / 5xx responses
client = SkytellsClient(retry={"retries": 3, "retry_delay": 1000})

Handling Prediction Failures

PREDICTION_FAILED is raised when the model itself fails during inference — the API accepted your request, but the prediction returned status: "failed". This is separate from API-level errors.

Common causes:

  • Invalid input that passed API validation but failed model-level validation
  • Content policy violation (Responsible AI)
  • Model capacity issues (retry usually resolves this)
  • Unsupported input format for the selected model
from skytells import SkytellsClient, SkytellsError, ApiErrorId

client = SkytellsClient()

try:
    prediction = client.run("truefusion-ultra", input={
        "prompt": "My generation prompt",
        "aspect_ratio": "16:9",
    })
    print(prediction.outputs())
except SkytellsError as e:
    if e.error_id == ApiErrorId.PREDICTION_FAILED:
        # Model inference failed — log and notify
        print("Generation failed:", e.message)
    else:
        raise

Handling Wait Timeouts

WAIT_TIMEOUT is raised when wait() (or run(), which calls wait() internally) exceeds max_wait before the prediction completes.

The prediction is still running on the server when this happens — it has not been cancelled. You can:

  • Cancel it via prediction.cancel()
  • Poll for it later via client.predictions.get(prediction_id)
  • Increase max_wait for slow models
from skytells import SkytellsClient, SkytellsError, ApiErrorId, WaitOptions

client = SkytellsClient()

# Start prediction without waiting
prediction = client.predict("mera", input={
    "prompt": "A drone shot over a mountain range",
    "seconds": "12",
    "size": "1280x720",
})

try:
    # Wait up to 5 minutes for slow models
    result = client.wait(prediction, WaitOptions(max_wait=300_000))
    print(result.outputs())
except SkytellsError as e:
    if e.error_id == ApiErrorId.WAIT_TIMEOUT:
        pred_id = prediction.id
        print(f"Timed out. Prediction {pred_id} is still running.")
        print("Cancel it:", prediction.cancel())
        # Or poll later:
        # later = client.predictions.get(pred_id)
    else:
        raise

Full Error Handler Pattern

A reusable pattern for production code that gracefully handles all common error scenarios:

from skytells import SkytellsClient, SkytellsError, ApiErrorId
import logging

logger = logging.getLogger(__name__)
client = SkytellsClient(retry={"retries": 3, "retry_delay": 1000})

def generate_image(prompt: str, model: str = "truefusion-pro") -> str | None:
    """
    Run a prediction and return the output URL, or None on failure.
    """
    try:
        prediction = client.run(model, input={"prompt": prompt})
        return prediction.outputs()

    except SkytellsError as e:
        match e.error_id:
            case ApiErrorId.UNAUTHORIZED:
                logger.error("API key is invalid. Set SKYTELLS_API_KEY correctly.")
                raise

            case ApiErrorId.MODEL_NOT_FOUND:
                logger.error(f"Model '{model}' not found. Check /docs/api/v1/models/catalog")
                raise

            case ApiErrorId.INSUFFICIENT_CREDITS:
                logger.warning("Insufficient credits. Top up at skytells.ai/billing")
                return None

            case ApiErrorId.RATE_LIMIT_EXCEEDED:
                # SDK retry should handle this, but just in case
                logger.warning("Rate limit hit after retries.")
                return None

            case ApiErrorId.PREDICTION_FAILED:
                logger.warning(f"Prediction failed: {e.message}")
                return None

            case ApiErrorId.WAIT_TIMEOUT:
                logger.warning("Prediction timed out — still running on the server.")
                return None

            case _:
                logger.error(f"Unexpected error [{e.error_id}]: {e.message}")
                raise

Async Error Handling

Error handling with AsyncSkytellsClient works identically — all the same error_id values apply, just inside async/await coroutines:

import asyncio
from skytells import AsyncSkytellsClient, SkytellsError, ApiErrorId

client = AsyncSkytellsClient()

async def main():
    try:
        prediction = await client.run("truefusion-pro", input={
            "prompt": "A photorealistic mountain lake at sunrise",
            "aspect_ratio": "16:9",
        })
        print(prediction.outputs())
    except SkytellsError as e:
        if e.error_id == ApiErrorId.RATE_LIMIT_EXCEEDED:
            print("Rate limited — try again shortly")
        elif e.error_id == ApiErrorId.PREDICTION_FAILED:
            print("Model failed:", e.message)
        else:
            raise

asyncio.run(main())

How is this guide?

On this page