Skip to content

Error Handling

The library maps PHP exceptions to OData-compliant error responses.

Error response format

All errors follow the OData error format:

json
{
  "error": {
    "code": "not_found",
    "message": "Entity with key 'id=999' not found in 'Products'.",
    "target": "Products(999)"
  }
}

Exception hierarchy

All protocol exceptions extend ProtocolException:

ExceptionHTTP StatusOData CodeWhen thrown
BadRequestException400bad_requestMalformed query options, invalid filter syntax, unknown properties
NotFoundException404not_foundEntity not found, unknown entity set
NotImplementedException501not_implementedUnsupported operations ($apply, write verbs, missing EntityResolverInterface)
InternalServerErrorException500internal_server_errorUnexpected server errors

Building error responses

Exceptions use a fluent API:

php
use LaravelUi5\OData\Exception\NotFoundException;

throw (new NotFoundException())
    ->code('entity_not_found')
    ->message("Product with id=42 not found.")
    ->target('Products(42)');

Adding details

php
throw (new BadRequestException())
    ->code('invalid_filter')
    ->message('The $filter expression is invalid.')
    ->addDetail('syntax_error', 'Unexpected token at position 15', '$filter')
    ->addInnerError('expression', "name eq 'Widget' and");

Produces:

json
{
  "error": {
    "code": "invalid_filter",
    "message": "The $filter expression is invalid.",
    "details": [
      {"code": "syntax_error", "message": "Unexpected token at position 15", "target": "$filter"}
    ],
    "innererror": {
      "expression": "name eq 'Widget' and"
    }
  }
}

Streaming error handling

When streaming is enabled in config (default), errors that occur mid-stream (after HTTP headers have been sent) are handled via HTTP trailers:

  1. The response starts streaming with HTTP 200
  2. If an exception occurs while yielding rows, the stream is terminated
  3. An odata-error trailer is appended with the error JSON

When streaming is disabled, the entire response is buffered. If an exception occurs, the buffer is discarded and a proper error response with the correct HTTP status code is sent.

Custom error responses

You can add custom headers to error responses:

php
throw (new BadRequestException())
    ->message('Rate limit exceeded')
    ->header('Retry-After', '60');

OData: MIT | Core: BSL 1.1 | SDK: Commercial License