rpc.error

← rpc.error

Ashterix

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

1 + # rpc.error
2 +
3 + ::::::block class="floatinginfobox floatinginfobox--fit"
4 + :::::columns border zebra
5 + ::::row
6 + :::col width="40%"
7 + **Event name**
8 + :::
9 + :::col
10 + `rpc.error`
11 + :::
12 + ::::
13 + ::::row
14 + :::col width="40%"
15 + **Constant**
16 + :::
17 + :::col
18 + `RpcEvent::ERROR`
19 + :::
20 + ::::
21 + ::::row
22 + :::col width="40%"
23 + **Class**
24 + :::
25 + :::col
26 + `RpcErrorEvent`
27 + :::
28 + ::::
29 + ::::row
30 + :::col width="40%"
31 + **Properties**
32 + :::
33 + :::col
34 + `RpcRequest $rpcRequest`, `Throwable $exception`, `RpcError $rpcError`
35 + :::
36 + ::::
37 + :::::
38 + ::::::
39 +
40 + An error during request execution. `$rpcError` is the error object the response will be built from; it can be replaced.
41 +
42 + ## When it is dispatched
43 +
44 + * Parameter validation and `#[RPC\Assertions]` errors.
45 + * Parameter conversion (DTO) errors.
46 + * An exception or `TypeError` from the method.
47 + * A request marked with an error at earlier stages (`setError()`).
48 + * In the console, inline batch and via `RpcExecutor` — also for any other processing exception.
49 +
50 + :::warning subtitle="Inconsistency"
51 + 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](/docs/api/json-rpc-bundle/developers/known_issues/open).
52 + :::
53 +
54 + ## Built-in listeners
55 +
56 + | Priority | Listener | What it does |
57 + | --- | --- | --- |
58 + | 1000 | `RpcErrorListener` | For `ConstraintsImposedException`, adds the list of violations to `data` |
59 + | 0 | `LoggerListener` | Logs the error (method, parameters, data) |
60 + | -1000 | `RpcServerListener::onRpcError` | Builds the error response from `$event->rpcError` (`rpc.pre_response`) and stops propagation |
61 +
62 + ## What can be changed
63 +
64 + `$event->rpcError` is the supported way to change the error the client receives:
65 +
66 + ```php
67 + $event->rpcError = new RpcError($code, $message, $data);
68 + ```
69 +
70 + * 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.
71 + * `$rpcError` is created from `$exception` in the constructor; assigning a new `$exception` does not recompute it.
72 + * Listeners below -1000 are not called. Do not stop propagation above -1000 — the error response will not be built.
73 +
74 + ## Usage examples
75 +
76 + ### Hiding internal details
77 +
78 + ```php
79 + #[AsEventListener(RpcEvent::ERROR, priority: 500)]
80 + final class HideInternalErrorsListener
81 + {
82 + public function __construct(#[Autowire('%kernel.environment%')] private string $env) {}
83 +
84 + public function __invoke(RpcErrorEvent $event): void
85 + {
86 + if ($this->env === 'prod' && $event->exception instanceof RpcRuntimeException) {
87 + $event->rpcError = new RpcError(-32500, 'Internal server error', []);
88 + }
89 + }
90 + }
91 + ```
92 +
93 + ### Sending to a monitoring system
94 +
95 + ```php
96 + #[AsEventListener(RpcEvent::ERROR, priority: 100)]
97 + final class SentryListener
98 + {
99 + public function __invoke(RpcErrorEvent $event): void
100 + {
101 + \Sentry\withScope(function (\Sentry\State\Scope $scope) use ($event): void {
102 + $scope->setTag('rpc.method', $event->rpcRequest->getMethod());
103 + \Sentry\captureException($event->exception);
104 + });
105 + }
106 + }
107 + ```
108 +
109 + ### Other ideas
110 +
111 + * converting the application's domain exceptions into custom error codes;
112 + * an error counter by method and code;
113 + * adding a `request_id` to the error `data` for support.