Hebbrix
Errors

Error Handling

Learn how to handle API errors gracefully. Hebbrix uses standard HTTP status codes and returns detailed error messages to help you debug issues.

Error Response Format

All error responses follow a consistent JSON format:

Error Response
{
  "error": {
    "code": "invalid_request",
    "message": "The 'content' field is required",
    "type": "validation_error",
    "param": "content",
    "status": 400,
    "request_id": "req_abc123xyz"
  }
}
FieldTypeDescription
codestringMachine-readable error code
messagestringHuman-readable error description
typestringError category (validation_error, auth_error, etc.)
paramstring?Parameter that caused the error (if applicable)
statusintegerHTTP status code
request_idstringUnique request ID for debugging

Error response schema

There are two error envelopes you may encounter. Most application errors use a structured error object:

Standard error envelope
{
  "error": {
    "type": "...",
    "message": "...",
    "status_code": 400
  }
}

Request-validation failures raised by FastAPI (HTTP 422) use the framework's detail array instead — each entry pinpoints the offending field:

422 Validation error
{
  "detail": [
    {
      "loc": ["body", "content"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

Common status codes

StatusMeaning
400Bad request (malformed body, or a destructive-action confirmation mismatch)
401Authentication failed (missing, invalid, or revoked API key)
403Forbidden (insufficient permission, or feature not available on your tier)
404Resource not found
422Request validation failed (see the detail array)
429Rate limited — honor Retry-After and retry
500Internal server error — safe to retry with backoff

Response headers & observability

Every response — whether it succeeds or fails — carries tracing headers. Capture these so support can trace a request end-to-end, and so retries stay safe.

HeaderDirectionDescription
X-Request-IDResponseA unique UUID attached to every response (success or error). Include it when reporting an issue so it can be traced in our logs.
X-Process-TimeResponseServer processing time, in milliseconds, emitted on every response.
Idempotency-KeyRequestSend on a POST/PUT/PATCH to make a retry safe. A duplicate request within a 24h window returns the original cached response.
X-Idempotent-ReplayResponseSet to true when a response was served from the idempotency cache rather than re-executed.
Retry-AfterResponseOn a 429, the number of seconds to wait before retrying.
X-RateLimit-LimitResponseOn a 429, the request ceiling for the current window.

Idempotent retries

Attach an Idempotency-Key to any write request. If the same key is replayed within 24 hours, the API returns the original cached response and marks it with X-Idempotent-Replay: true — so a network-level retry never creates a duplicate.

Idempotent retry
POST /v1/memories HTTP/1.1
Authorization: Bearer mem_sk_...
Idempotency-Key: 9f1c2b6e-7a3d-4e51-9c08-2b5d8e4a1f60
Content-Type: application/json

# A retry of the exact same request returns the first response:
HTTP/1.1 201 Created
X-Request-ID: 3f9a0c1d-8e2b-4a77-bd31-6c2f9e0a4b15
X-Process-Time: 0.42
X-Idempotent-Replay: true

Rate limiting

When you are throttled the API responds with HTTP 429, a Retry-After value (seconds) and X-RateLimit-Limit. Space your bursts and honor Retry-After. Per-request remaining-count headers on successful 2xx responses are not currently emitted, so do not rely on a remaining-count header to pace requests.

HTTP Status Codes

400

Bad Request

The request was malformed or missing required parameters.

Missing required fieldsInvalid JSON bodyInvalid parameter types
401

Unauthorized

Authentication failed or API key is invalid.

Missing API keyInvalid API key formatRevoked API key
403

Forbidden

The API key doesn't have permission for this action.

Insufficient permissionsResource belongs to another userFeature not available on tier
404

Not Found

The requested resource doesn't exist.

Invalid IDResource was deletedTypo in endpoint URL
429

Too Many Requests

Rate limit exceeded. Slow down your requests.

Exceeded requests per minuteExceeded monthly credit quota
500

Internal Server Error

Something went wrong on our end. Retry the request.

Temporary system issueDatabase error

Error Codes

Common error codes returned in the error.code field:

CodeDescription
invalid_api_keyThe API key provided is invalid or expired
missing_api_keyNo API key was provided in the request
invalid_requestThe request body is malformed or missing fields
validation_errorA parameter failed validation rules
resource_not_foundThe requested resource doesn't exist
collection_not_foundThe specified collection doesn't exist
rate_limit_exceededToo many requests in the time window
quota_exceededMonthly credit quota has been exceeded
document_too_largeUploaded file exceeds size limit
unsupported_formatFile format is not supported
permission_deniedThe API key lacks required permissions
feature_not_availableFeature requires a higher tier (returned as 403; payload includes required_tier, upgrade_url, pricing_url)
internal_errorAn unexpected server error occurred

403 feature_not_available payload

When a tier-gated feature is called from a tier that doesn't include it, the backend returns HTTP 403 with the structured payload below (emitted by tier_features.get_upgrade_message):

403 Feature Not Available
{
  "error": "feature_not_available",
  "feature": "knowledge_graph",
  "feature_name": "Knowledge Graph",
  "message": "Knowledge Graph requires Pro plan or higher.",
  "current_tier": {
    "name": "free",
    "display_name": "Free"
  },
  "required_tier": {
    "name": "pro",
    "display_name": "Pro",
    "price": "$99/month",
    "credits": "200K/month"
  },
  "upgrade_url": "https://app.hebbrix.com/dashboard/billing",
  "pricing_url": "https://app.hebbrix.com/pricing"
}

Handling Errors

Python

Python Error Handling
import asyncio
from hebbrix import MemoryClient
from hebbrix import (
    HebbrixError,
    AuthenticationError,
    RateLimitError,
    ValidationError,
    NotFoundError,
)

async def main():
    async with MemoryClient(api_key="mem_sk_...") as client:
        try:
            memory = await client.memories.create(
                collection_id="col_xyz",
                content="Test memory",
            )
        except AuthenticationError as e:
            # Invalid or missing API key
            print(f"Auth error: {e}")

        except RateLimitError as e:
            # Too many requests — backend returned 429
            print(f"Rate limited: {e}")

        except ValidationError as e:
            # 422 — request body/params failed backend validation
            print(f"Validation error: {e}")

        except NotFoundError as e:
            # 404 — the collection or memory doesn't exist
            print(f"Not found: {e}")

        except HebbrixError as e:
            # Catch-all for any other API error (5xx, etc.)
            print(f"API error: {e}")

asyncio.run(main())

TypeScript

TypeScript Error Handling
import {
  MemoryClient,
  HebbrixError,
  AuthenticationError,
  RateLimitError,
  ValidationError,
  NotFoundError,
} from 'hebbrix';

const client = new MemoryClient({ apiKey: 'mem_sk_...' });

try {
  await client.memories.create({
    collectionId: 'col_xyz',
    content: 'Test memory',
  });
} catch (error) {
  if (error instanceof AuthenticationError) {
    // Invalid or missing API key
    console.error('Auth error:', error.message);

  } else if (error instanceof RateLimitError) {
    // Too many requests
    console.error('Rate limited:', error.message);
    // Wait a bit and retry

  } else if (error instanceof ValidationError) {
    // 422 — backend rejected the request body
    console.error('Validation error:', error.message);

  } else if (error instanceof NotFoundError) {
    // 404 — resource doesn't exist
    console.error('Not found:', error.message);

  } else if (error instanceof HebbrixError) {
    // Catch-all for other API errors
    console.error(`API error [${error.status}]: ${error.message}`);
    console.error(`Request ID: ${error.requestId}`);

  } else {
    throw error; // Re-throw unknown errors
  }
}

Rate Limit Handling

When you hit rate limits, the response includes headers to help you retry appropriately:

429 Response
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705312800
Retry-After: 45

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Please retry after 45 seconds.",
    "type": "rate_limit_error",
    "status": 429,
    "request_id": "req_xyz789"
  }
}

Implementing Exponential Backoff

Python Exponential Backoff
import asyncio
import random
from hebbrix import MemoryClient
from hebbrix import RateLimitError, HebbrixError

async def create_with_retry(client: MemoryClient, max_retries: int = 5):
    """Retry with exponential backoff + jitter on 429 / 5xx."""
    for attempt in range(max_retries):
        try:
            return await client.memories.create(
                collection_id="col_xyz", content="Test"
            )
        except RateLimitError:
            if attempt == max_retries - 1:
                raise
            sleep = (2 ** attempt) + random.uniform(0, 1)
            print(f"Rate limited — retry in {sleep:.1f}s")
            await asyncio.sleep(sleep)
        except HebbrixError:
            if attempt == max_retries - 1:
                raise
            sleep = (2 ** attempt) + random.uniform(0, 1)
            print(f"Transient error — retry in {sleep:.1f}s")
            await asyncio.sleep(sleep)


async def main():
    async with MemoryClient(api_key="mem_sk_...") as client:
        await create_with_retry(client)


asyncio.run(main())

Best Practices

Always Handle Errors

Wrap API calls in try/catch and handle specific error types appropriately.

Implement Retries

Use exponential backoff for rate limits (429) and server errors (5xx).

Log Request IDs

Save the request_id for debugging. Include it when contacting support.

Don't Expose Errors

Don't show raw API errors to end users. Display friendly messages instead.

Next Steps

Assistant

Ask me anything about Hebbrix