Learn / Errors and failures

Reads

A read is a RemoteData: Initial, Loading, Ready, Refreshing, Failed { error, previous } or NotFound. RemoteData.match is the exhaustive fold over the six; RemoteData.render the view's fold above. Initial is not a failure but is often a mistake: nothing is fetching the read, which a spinner hides. Data.why(model, read, { surfaces: actives }) says why: which list or which field of which row is missing, stale, in flight or failed, and what restarts it.

A RemoteError is { _tag, message }, with reason for a refusal of who is asking and refusal for a mutation's declared refusal. Its _tag is open, since a transport may report any failure. The ones Remote and its server send:

_tagMeaningAsking again
RemoteReadError, RemoteQueryErrorthe request failed: the network, or the server's Source (its message)may work
RemoteMutationErrora mutation failed: the server's Source (its message), or the mutation's declared refusal (refusal, which Data.refusal decodes)may work; a refusal will not, with the same input
Unreachablea mutation nothing answered: it could not be sent, or what came back was no answer (a gateway's 502 page); the server may or may not have run itas the same write (Data.retry), which a ledgered writer answers from its record; a durable write is sent again on its own
RemoteLiveErrora live stream broke; Data.liveStatus carries it while the stream restarts itselfnot needed
RemoteProtocolErrorclient and server speak different protocol versionsnever: deploy one version
DecodeErrorwhat the server sent does not decode against the Selectionnever: the shapes disagree
Unavailablethe server settled a selected field without a valuenever: select without it
Overlaida read of a row only overlays show lacks a field nothing will fetchnever: overlay what it reads
Unauthenticatedwho is asking could not be told: no session, or one that endedafter signing in
Forbiddenwho is asking may not do this; a write the held may says no to is refused so where it is madenever, as the same person

A failure reaches every read that needs it: a list fails when a field of one of its rows failed, a project when its owner's read did. One that showed a value keeps it as previous. A list whose rows are still arriving reads Refreshing and draws the rows it can assemble, so a row entering unread never hides the rows already shown.

A broken live stream is not a failed read. It records a gap, keeps what the server last said, and restarts on its own with backoff, refetching what it covered; Data.liveStatus(model, active) reads Reconnecting with the error meanwhile. A stream the server refuses for what it asks (RemoteLiveRefused, over maxIdsPerEntity) is not restarted: it reads Refused until its requirements change. See When a stream breaks.

Data.inspect(model).failures lists every unsettled failed read, by connection and by field, beside what is loading and the diagnostics Remote recorded. The Remote README lists everything that settles a failure.