Learn / Errors and failures
The server: what a client is told
A server answers every failure; what it says is chosen so that nothing
internal leaks. Over RemoteServer.answer and serveFetch:
| On the server | The client receives |
|---|---|
A Source fails with RemoteServerError(message) | RemoteReadError, RemoteQueryError or RemoteMutationError with that message: write it for the reader |
RemoteServer.refuse(mutation, refusal) | a 422 with the refusal (a 409 for a Refusal.taken), which Data.refusal decodes |
A writer's RemoteServer.taken(), for a declared insert of a taken id | a 409 with the mutation's Taken refusal, naming only the Entity and the id |
RemoteServer.forbid(reason?) | a 403, _tag: 'Forbidden', with reason only when given |
RemoteServer.unauthenticated(reason?) from a resolver | a 401, _tag: 'Unauthenticated', with reason only when given |
| A mutation's input does not decode | Invalid mutation input, and nothing of the schema's message |
A field authorize withholds | the field settled, never why; an id withheld whole reads like an id that does not exist |
| A Drizzle statement fails | Database query failed for a read or query, Database write failed for a write; the driver's error goes to StatementFailed |
| A defect, or a layer or resolver that breaks | a 500, Internal error; the cause goes to ServerDefect |
| A write committed and its answer's read failed | the answer without the rows; the client reads them again (AnswerUnread) |
| A write committed and its live publish failed | the write's answer; live subscribers do not hear it (PublishFailed) |
serveFetch takes diagnostics: (diagnostic, request) => Effect, used for
everything that request runs, a broken layer included; without it the
reporter in the Effect context is used. See the remote-server
Diagnostics and
Hardening.