Skip to content

Exception Handling

The client raises exceptions if the API returns an error response. Most of the time, you should catch ApiException (and subclasses) to handle any HTTP error.

Already have an error handling strategy?

Read on how to change your code to use the client's exceptions to match your strategy.

Error forwarding

The client forwards the error response from the API to the exception. HTTP status codes are not altered, but forwarded as is.

Exception hierarchy

Examples

Catching any HTTP error

Catch ApiException to handle any HTTP error.

from immichpy import AsyncClient
from immichpy.client.generated.exceptions import ApiException

async def get_server_version(base_url: str, api_key: str) -> None:
    async with AsyncClient(api_key=api_key, base_url=base_url) as client:
        try:
            version = await client.server.get_server_version()
            print(f"{version.major}.{version.minor}.{version.patch}")
        except ApiException as e:
            print(f"API error: status={e.status}, body={e.body}")
            raise

Timeout

When you set a timeout on the request, you can catch it with asyncio.TimeoutError:

import asyncio
import aiohttp
from immichpy import AsyncClient
from immichpy.client.generated.exceptions import ApiException

async def get_server_version_with_timeout(base_url: str, api_key: str) -> None:
    session = aiohttp.ClientSession(
        timeout=aiohttp.ClientTimeout(connect=5, sock_read=60),
    )
    async with AsyncClient(
        api_key=api_key,
        base_url=base_url,
        http_client=session,
    ) as client:
        try:
            version = await client.server.get_server_version()
            print(f"{version.major}.{version.minor}.{version.patch}")
        except ApiException as e:
            print(f"API error: status={e.status}, body={e.body}")
            raise
        except asyncio.TimeoutError as e:
            print("Request timed out")
            raise

Authentication errors (401, 403)

Catch UnauthorizedException (401) and ForbiddenException (403) when validating an API key or user access, and surface a clear message to the user:

from immichpy import AsyncClient
from immichpy.client.generated.exceptions import (
    ApiException,
    ForbiddenException,
    UnauthorizedException,
)

async def validate_api_key(base_url: str, api_key: str) -> str:
    async with AsyncClient(api_key=api_key, base_url=base_url) as client:
        try:
            user_dto = await client.users.get_my_user()
            return str(user_dto.id)
        except (UnauthorizedException, ForbiddenException) as e:
            raise ValueError("Invalid Immich API key or no access to the API.") from e

Conflict or unprocessable (409, 422)

When creating a resource that might already exist (e.g. album by name), catch ConflictException (409) and UnprocessableEntityException (422) to raise a clear error message.

from immichpy import AsyncClient
from immichpy.client.generated import CreateAlbumDto
from immichpy.client.generated.exceptions import (
    ConflictException,
    UnprocessableEntityException,
)

async def ensure_album_exists(client: AsyncClient, album_name: str) -> str:
    try:
        new_album = await client.albums.create_album(
            create_album_dto=CreateAlbumDto(albumName=album_name),
        )
        return str(new_album.id)
    except (ConflictException, UnprocessableEntityException):
        raise ValueError(f"Album '{album_name}' already exists") from e