Skip to content

Errors

beginner

HTTP error codes, error response format, rate limiting, troubleshooting guide, and retry strategies.

Error response format

All errors return a consistent JSON structure:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The 'text' field is required",
    "status": 422,
    "details": {
      "field": "text",
      "constraint": "required"
    },
    "request_id": "req_abc123def456"
  }
}
FieldDescription
codeMachine-readable error code (uppercase snake_case)
messageHuman-readable explanation
statusHTTP status code
detailsAdditional context (varies by error type)
request_idUnique identifier for support requests

HTTP status codes

400 Bad Request

GET400 BAD_REQUEST

The request body is malformed or cannot be parsed.

CodeMessageFix
INVALID_JSONRequest body is not valid JSONCheck JSON syntax, ensure Content-Type is application/json
INVALID_PARAMETERParameter value is out of rangeCheck parameter constraints in the endpoint docs
MISSING_BODYRequest body is requiredAdd a JSON body to the request

401 Unauthorized

GET401 UNAUTHORIZED

Authentication failed or was not provided.

CodeMessageFix
MISSING_API_KEYNo API key or Bearer token providedAdd X-API-Key header or Authorization: Bearer header
INVALID_API_KEYAPI key is malformed or doesn't existCheck key format (nx_live_ or nx_test_, 48 chars)
EXPIRED_TOKENJWT access token has expiredRefresh using /v1/auth/refresh
REVOKED_KEYAPI key has been revokedCreate a new API key
from engramma_cloud import EngrammaClient, AuthenticationError

try:
    client = EngrammaClient(api_key="invalid_key")
    client.stats()
except AuthenticationError as e:
    print(f"Auth failed: {e.code}")  # "INVALID_API_KEY"
    print(f"Message: {e.message}")

403 Forbidden

GET403 FORBIDDEN

Authentication succeeded but you don't have permission for this action.

CodeMessageFix
INSUFFICIENT_SCOPEAPI key doesn't have the required scopeCreate a key with the needed scope (e.g., memory:write)
MEMBER_NOT_ADMINAction requires admin roleAsk an org admin to perform this action
ORG_NOT_MEMBERYou're not a member of this organizationRequest an invitation from an org admin

404 Not Found

GET404 NOT_FOUND

The requested resource doesn't exist.

CodeMessageFix
MEMORY_NOT_FOUNDNo memory with this ID existsVerify the memory ID, it may have been deleted or consolidated
ORG_NOT_FOUNDOrganization doesn't existCheck the org ID
USER_NOT_FOUNDUser doesn't existVerify the user/member ID
ENDPOINT_NOT_FOUNDURL path doesn't match any endpointCheck the API docs for correct paths

409 Conflict

GET409 CONFLICT

The request conflicts with current state.

CodeMessageFix
EMAIL_ALREADY_EXISTSEmail is already registeredUse login instead, or use a different email
KEY_NAME_EXISTSAn API key with this name already existsChoose a different name
CONSOLIDATION_IN_PROGRESSA consolidation cycle is already runningWait for it to complete (check sleep-stats)

422 Unprocessable Entity

GET422 VALIDATION_ERROR

The request is well-formed but fails validation.

CodeMessageFix
VALIDATION_ERRORField-level validation failureCheck the details.field for which field failed
TEXT_TOO_LONGText exceeds 10,000 character limitShorten the text or split into multiple memories
BATCH_TOO_LARGEBatch exceeds 100 itemsSplit into smaller batches
INVALID_METADATAMetadata exceeds size limitsKeep metadata under 10KB per memory
PASSWORD_TOO_WEAKPassword doesn't meet requirementsUse 8+ chars with uppercase, lowercase, and number

429 Too Many Requests

GET429 RATE_LIMITED

You've exceeded your plan's rate limit.

CodeMessageFix
RATE_LIMITEDToo many requestsWait for Retry-After seconds, then retry
BURST_EXCEEDEDBurst limit exceededSpread requests over a longer window
DAILY_LIMIT_REACHEDDaily API call limit reached (Free tier)Upgrade plan or wait until tomorrow

Rate limit headers on 429 responses:

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 50
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705312800
Retry-After: 3
from engramma_cloud import EngrammaClient, RateLimitError
import time

client = EngrammaClient(api_key=os.environ["ENGRAMMA_API_KEY"])

try:
    result = client.retrieve("query")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
    time.sleep(e.retry_after)
    result = client.retrieve("query")  # Retry

# The SDK handles retries automatically by default

500 Internal Server Error

GET500 INTERNAL_ERROR

Something went wrong on our side.

CodeMessageFix
INTERNAL_ERRORAn unexpected error occurredRetry the request. If persistent, contact support with the request_id
SERVICE_UNAVAILABLEThe service is temporarily downCheck status.engramma-memory.com

Retry strategy

The SDKs implement automatic retries with exponential backoff:

AttemptDelayRetries on
1st retry1s429, 500, 503
2nd retry2s429, 500, 503
3rd retry4s429, 500, 503
Give upReturns the last error

Never retry:

  • 400 (bad request — fix the input)
  • 401 (auth failed — fix credentials)
  • 403 (forbidden — fix permissions)
  • 404 (not found — resource doesn't exist)
  • 409 (conflict — resolve the conflict)
  • 422 (validation — fix the data)
# Configure retry behavior
client = EngrammaClient(
    api_key=os.environ["ENGRAMMA_API_KEY"],
    max_retries=3,           # Default: 3
    retry_delay=1.0,         # Base delay in seconds
    retry_backoff=2.0        # Exponential backoff multiplier
)

Error handling best practices

  1. Always check error.code — not just the HTTP status. Multiple error types share the same status code.

  2. Log the request_id — include it in support tickets for fast debugging.

  3. Handle rate limits gracefully — the Retry-After header tells you exactly how long to wait.

  4. Don't retry client errors — 4xx errors (except 429) won't succeed on retry.

  5. Use SDK error classes — they provide typed access to error details.

Tip

When reporting issues, include the request_id from the error response. This lets support trace your exact request through the system.

Next steps