Skip to main content
The SDK raises typed exceptions for API failures, validation issues, and network problems. Catch and handle them for robust integrations.

Exception classes

DevhelmError

The base exception for all API errors:
from devhelm import DevhelmError

try:
    client.monitors.get("nonexistent")
except DevhelmError as e:
    print(e.code)     # "NOT_FOUND"
    print(e.status)   # 404
    print(e.message)  # "Monitor not found"
    print(e.detail)   # optional additional context
PropertyTypeDescription
codestrError category
statusintHTTP status code
messagestrHuman-readable error message
detailstr | NoneAdditional context

AuthError

Raised for authentication and authorization failures (401, 403):
from devhelm import AuthError

try:
    client.monitors.list()
except AuthError:
    print("Check your API token")
AuthError extends DevhelmError with code always set to "AUTH".

Error codes

CodeHTTP statusDescription
AUTH401, 403Invalid or expired token, insufficient permissions
NOT_FOUND404Resource does not exist
CONFLICT409Resource conflict (e.g., deploy lock held)
VALIDATION400, 422Invalid request body or parameters
API5xx, otherServer error or unexpected response

Handling patterns

Catch specific error codes

from devhelm import DevhelmError, AuthError

try:
    monitor = client.monitors.create({
        "name": "API Health",
        "type": "HTTP",
        "config": {"url": "https://api.example.com/health"},
        "frequencySeconds": 60,
    })
except AuthError:
    print("Authentication failed — check your token")
except DevhelmError as e:
    if e.code == "VALIDATION":
        print(f"Invalid request: {e.detail}")
    elif e.code == "CONFLICT":
        print("Resource already exists")
    else:
        print(f"API error ({e.status}): {e.message}")

Retry with backoff

import time
from devhelm import DevhelmError

def with_retry(fn, max_retries=3):
    for attempt in range(max_retries + 1):
        try:
            return fn()
        except DevhelmError as e:
            if e.status == 429 and attempt < max_retries:
                delay = 2 ** attempt
                time.sleep(delay)
                continue
            raise

monitors = with_retry(client.monitors.list)

Deploy lock contention

from devhelm import DevhelmError

try:
    lock = client.deploy_lock.acquire({
        "lockedBy": "ci-pipeline",
        "ttlMinutes": 30,
    })
except DevhelmError as e:
    if e.code == "CONFLICT":
        current = client.deploy_lock.current()
        if current:
            print(f"Lock held by {current['lockedBy']}")

Network errors

The SDK uses httpx under the hood. Network-level errors (timeouts, DNS failures, connection refused) raise httpx exceptions, not DevhelmError:
import httpx
from devhelm import DevhelmError

try:
    client.monitors.list()
except httpx.TimeoutException:
    print("Request timed out")
except httpx.ConnectError:
    print("Could not connect to API")
except DevhelmError as e:
    print(f"API error: {e.message}")

Next steps

Client reference

Full method reference for all resources.

Error patterns

Common error scenarios across all surfaces.