Error Handling

OtterApi uses OtterApiException for all structured error responses. Throw it from any BeforeSave or AfterSave hook to return a machine-readable JSON error to the client. The middleware catches it automatically.

OtterApiException

Throwing from a hook
throw new OtterApiException(
    code:       "OUT_OF_STOCK",
    message:    "Cannot create order: the product is out of stock.",
    statusCode: 422
);

Constructor parameters

ParameterTypeDefaultDescription
codestringrequiredMachine-readable error code (e.g. "OUT_OF_STOCK")
messagestringrequiredHuman-readable error description
statusCodeint400HTTP status code to return

Response format

The middleware catches the exception and returns a JSON body:

HTTP Response
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "code":    "OUT_OF_STOCK",
  "message": "Cannot create order: the product is out of stock."
}

Built-in error codes

OtterApi itself throws OtterApiException in the following situations:

CodeStatusWhen
INVALID_BODY 400 Request body (POST / PUT) is null or empty
INVALID_FILTER_OPERATOR 400 Client uses an operator not supported for the property type (e.g. filter[price][like]=foo)
INVALID_JSON 400 Request body (POST / PUT / PATCH) contains invalid JSON, or filter[...][in] value is not a valid JSON array
CONFLICT 409 Database unique or primary-key constraint violation
DB_UPDATE_ERROR 422 Database update failed for another reason (FK violation, check constraint, etc.)
KEYLESS_ENTITY 405 POST / PUT / PATCH / DELETE attempted on a keyless entity

Validation errors (400)

OtterApi validates Data Annotations ([Required], [MaxLength], etc.) on incoming POST and PUT bodies using the standard IObjectModelValidator. Invalid requests return 400 Bad Request with the model state error details.

Example 400 response (missing required field)
HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "Name": ["The Name field is required."]
}