Error Codes
All error responses follow a consistent JSON format:
{ "error": "Human-readable description of what went wrong", "errorCode": "SNAKE_CASE_ERROR_CODE"}Some errors include additional fields with context (e.g., expectedVersion and actualVersion on concurrency conflicts).
Error Reference
Section titled “Error Reference”| Error Code | HTTP Status | Description |
|---|---|---|
VALIDATION_ERROR | 400 | Request validation failed — missing or invalid fields |
INVALID_REQUEST | 400 | Malformed request body — could not parse JSON |
INVALID_UPLOAD | 400 | File upload issue — missing file or wrong content type |
INVALID_ZIP | 400 | Cannot extract zip contents |
INVALID_CONTENTS | 400 | Zip missing required .cs files |
FILE_TOO_LARGE | 400 | Upload exceeds 5MB limit |
INVALID_REDUCER | 400 | Attempted to bind a projection as a reducer |
REDUCER_NOT_READY | 400 | Reducer is still compiling — wait and retry |
AGGREGATE_TYPE_MISMATCH | 400 | Aggregate already has events with a different type |
UNAUTHORIZED | 401 | Invalid or missing API key |
NOT_FOUND | 404 | Resource not found |
NO_REDUCER_BOUND | 404 | No reducer configured for this aggregate type |
CONCURRENCY_CONFLICT | 409 | Version mismatch — another process modified the aggregate |
INTERNAL_ERROR | 500 | Server error — retry or contact support |
Handling Errors by Status Code
Section titled “Handling Errors by Status Code”400 — Bad Request
Section titled “400 — Bad Request”Your request is invalid. Check the errorCode and error message for specifics. These are not retryable — fix the request and try again.
401 — Unauthorized
Section titled “401 — Unauthorized”Your API key is missing, invalid, or expired. Check the X-API-Key header.
404 — Not Found
Section titled “404 — Not Found”The resource doesn’t exist. For state queries, this can mean either the aggregate doesn’t exist or no reducer is bound — check the errorCode to distinguish (NOT_FOUND vs NO_REDUCER_BOUND).
409 — Concurrency Conflict
Section titled “409 — Concurrency Conflict”The expectedVersion you specified doesn’t match the aggregate’s current version. Another process appended events since you last read the state.
{ "error": "Concurrency conflict", "errorCode": "CONCURRENCY_CONFLICT", "expectedVersion": 5, "actualVersion": 7}The correct response is to reload the current state, re-evaluate your business logic, and retry with the new version.
500 — Internal Error
Section titled “500 — Internal Error”Something went wrong on the server. These are safe to retry. If the problem persists, check the health endpoint.
SDK Error Mapping
Section titled “SDK Error Mapping”The SDKs map these error codes to typed exceptions/errors automatically:
| Error Code | SDK Exception |
|---|---|
CONCURRENCY_CONFLICT | HapndConcurrencyException |
AGGREGATE_TYPE_MISMATCH | HapndAggregateTypeMismatchException |
VALIDATION_ERROR | HapndValidationException |
| Other 4xx/5xx | HapndApiException |
| Network failure | HapndNetworkException |
TypeScript
Section titled “TypeScript”| Error Code | SDK Error |
|---|---|
CONCURRENCY_CONFLICT | HapndConcurrencyError |
AGGREGATE_TYPE_MISMATCH | HapndAggregateTypeMismatchError |
VALIDATION_ERROR | HapndValidationError |
| Other 4xx/5xx | HapndApiError |
| Network failure | HapndNetworkError |
| Circuit breaker open | HapndCircuitOpenError |