Learn / Errors and failures

The mental model

a failure the reader can act on
  └─▶ a typed value ──Message──▶ update ──▶ Model ──▶ view draws it ──▶ the reader acts ──▶ Message

a failure only a developer can fix
  └─▶ a Diagnostic ──Diagnostics.report──▶ Diagnostics.Reporter ──▶ Effect's log, or your sink

Three rules follow from it.

  • A value once shown stays on screen. A refresh that fails keeps the value it was refreshing; a list keeps the rows it can draw. A reader keeps working with what they had, told that it may be stale. One case breaks it: a field that only a write's optimistic layer showed, and that its answer left out, reads Loading until it is fetched again. The answer carries what the Surfaces show of every row it names, so this is a row the server did not name, or an answer whose read failed (AnswerUnread); verifyPredictions reports such a field as a PredictionMismatch's Gap (see Checking an answer against what was shown).
  • Nothing a reader started is retried on its own. A failed read waits for Data.refresh, and a failed write for Data.retry. A persistent error asked again on every unrelated change would hammer the server and hide the failure. Only the transports retry by themselves (a live stream, a Sync exchange, the durable outbox sending a write nothing answered), since asking again changes nothing the reader sees.
  • A diagnostic never changes behaviour. A read, a write and a placement behave the same whether one is reported or not. The channel says why; it decides nothing.