Guides

Error Handling

The typed exception hierarchy and how to catch each case.

All SDK calls throw/raise instances of a single exception tree. Catching the right one lets you distinguish "need to reconnect" from "upgrade your plan" from "bad credentials".

Both SDKs expose the same fine-grained hierarchy mapped from the API's error_code. Python uses bare class names (AuthorizationError); Node prefixes everything with Memsy (MemsyAuthorizationError).

The hierarchy

MemsyError
├── MemsyConnectionError        # network error or timeout
└── MemsyAPIError               # non-2xx HTTP response
    ├── AuthenticationError     # 401 — invalid or missing API key
    ├── AuthorizationError      # 403 — key lacks the required scope
    ├── FeatureNotAvailable     # 403 — feature not on your tier
    ├── OrgIdNotAllowedError    # 400 — free-tier: org_id not allowed in request
    ├── SeatRequiredError       # 403 — endpoint requires an assigned seat
    ├── OrgLimitReachedError    # 403 — org tier limit reached
    ├── KeyLimitReachedError    # 403 — API key tier limit reached
    ├── BillingNotEnabledError  # 403 — billing not enabled for this org
    ├── SeatLimitReachedError   # 409 — purchased seat limit reached
    ├── RateLimitExceeded       # 429 — rate limit hit (after retries)
    └── UsageLimitExceeded      # 429 — plan quota exceeded

A full example

Imports come from memsy.exceptions:

from memsy import MemsyClient
from memsy.exceptions import (
    AuthenticationError,
    AuthorizationError,
    FeatureNotAvailable,
    RateLimitExceeded,
    UsageLimitExceeded,
    MemsyConnectionError,
    MemsyAPIError,
)

client = MemsyClient(base_url="...", api_key="***")

try:
    results = client.search("preferences")
except AuthenticationError:
    refresh_api_key()
except AuthorizationError as e:
    print(f"Missing required scope: {e.required_scope}")
except FeatureNotAvailable as e:
    print(f"Feature '{e.feature}' requires an upgrade from {e.current_tier}")
    print(f"Upgrade at: {e.upgrade_url}")
except RateLimitExceeded as e:
    print(f"Rate limited; retry after {e.retry_after}s")
except UsageLimitExceeded as e:
    print(f"Hit {e.dimension} limit ({e.current}/{e.limit})")
    print(f"Upgrade at: {e.upgrade_url}")
except MemsyConnectionError:
    ...
except MemsyAPIError as e:
    print(f"API error {e.status_code}: {e.detail}")

Control-plane errors (Python only)

MemsyControlClient is currently Python-only. When using it, you may also encounter:

from memsy.exceptions import (
    OrgLimitReachedError,
    KeyLimitReachedError,
    BillingNotEnabledError,
    SeatRequiredError,
    SeatLimitReachedError,
)

try:
    key = control.keys.create("my-key", scopes=["read", "write"])
except KeyLimitReachedError as e:
    print(f"Key limit reached: {e.current}/{e.limit}")
except BillingNotEnabledError as e:
    print(f"Billing not enabled. Express interest at: {e.interest_path}")

Exception-specific attributes (Python)

AuthorizationError

AttributeDescription
required_scopeScope your API key is missing, if known.

FeatureNotAvailable

AttributeDescription
featureThe gated feature's identifier.
current_tierThe tier of the API key that tried to use it.
upgrade_urlDeep-link to the dashboard billing page.

OrgLimitReachedError / KeyLimitReachedError

AttributeDescription
limitTier limit (orgs or keys).
currentCurrent count.

BillingNotEnabledError

AttributeDescription
interest_pathAPI path to express Pro plan interest.

SeatLimitReachedError

AttributeDescription
purchased_seatsTotal purchased seats.
assigned_seatsCurrently assigned seats.
pending_invitesPending invite count.

RateLimitExceeded

AttributeDescription
retry_afterSeconds to wait before retrying, parsed from Retry-After.

UsageLimitExceeded

AttributeDescription
dimensionWhat quota was exhausted (e.g. "events_ingested").
currentCurrent usage count.
limitThe limit that was exceeded.
upgrade_urlDeep-link to upgrade.

MemsyAPIError (base class)

Every API-side error carries:

AttributeDescription
status_codeHTTP status.
detailServer-provided message.
error_codeStable machine-readable code, e.g. "feature_not_available".
responseThe raw httpx.Response for deeper inspection.

Catch broadly or narrowly?

  • In request handlers / agent loops — catch MemsyError and surface a friendly error. Log the specific subclass for debugging.
  • In pipelines with budgets — handle UsageLimitExceeded and FeatureNotAvailable distinctly so you can route to an alert channel and link the upgrade page.
  • In retryable background jobs — catch MemsyConnectionError and RateLimitExceeded separately from API-level errors; they're the only ones that "just work" on a later retry.
  • In control-plane admin code — handle BillingNotEnabledError and SeatLimitReachedError and link users to the appropriate dashboard flow.

Next

  • How automatic 429 retry behaves before these exceptions fire → Retries.