docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api
en/docs/api/json-rpc-bundle/functionality/events/error.md
new file +113
−0
rpc.error
Event name
rpc.error
Constant
RpcEvent::ERROR
Class
RpcErrorEvent
Properties
RpcRequest $rpcRequest, Throwable $exception, RpcError $rpcError
An error during request execution. $rpcError is the error object the response will be built from; it can be replaced.
When it is dispatched
- Parameter validation and
#[RPC\Assertions]errors. - Parameter conversion (DTO) errors.
- An exception or
TypeErrorfrom the method. - A request marked with an error at earlier stages (
setError()). - In the console, inline batch and via
RpcExecutor— also for any other processing exception.
Inconsistency
In a single HTTP request, some errors (invalid JSON, token, unknown method, jsonrpc version, batch) do not go through rpc.error and are not logged by the bundle. Details — in Open issues.
Built-in listeners
| Priority | Listener | What it does |
|---|---|---|
| 1000 | RpcErrorListener |
For ConstraintsImposedException, adds the list of violations to data |
| 0 | LoggerListener |
Logs the error (method, parameters, data) |
| -1000 | RpcServerListener::onRpcError |
Builds the error response from $event->rpcError (rpc.pre_response) and stops propagation |
What can be changed
$event->rpcError is the supported way to change the error the client receives:
$event->rpcError = new RpcError($code, $message, $data);
- Priority between 1000 and 0 — your version goes both to the log and to the client; between 0 and -1000 — the log sees the original.
$rpcErroris created from$exceptionin the constructor; assigning a new$exceptiondoes not recompute it.- Listeners below -1000 are not called. Do not stop propagation above -1000 — the error response will not be built.
Usage examples
Hiding internal details
#[AsEventListener(RpcEvent::ERROR, priority: 500)]
final class HideInternalErrorsListener
{
public function __construct(#[Autowire('%kernel.environment%')] private string $env) {}
public function __invoke(RpcErrorEvent $event): void
{
if ($this->env === 'prod' && $event->exception instanceof RpcRuntimeException) {
$event->rpcError = new RpcError(-32500, 'Internal server error', []);
}
}
}
Sending to a monitoring system
#[AsEventListener(RpcEvent::ERROR, priority: 100)]
final class SentryListener
{
public function __invoke(RpcErrorEvent $event): void
{
\Sentry\withScope(function (\Sentry\State\Scope $scope) use ($event): void {
$scope->setTag('rpc.method', $event->rpcRequest->getMethod());
\Sentry\captureException($event->exception);
});
}
}
Other ideas
- converting the application's domain exceptions into custom error codes;
- an error counter by method and code;
- adding a
request_idto the errordatafor support.