API reference › @evolu/common › local‑first/Evolu › EvoluError
type EvoluError =
| DatabaseHeldError
| OtherBuildRunningError
| UnknownError
| UnsupportedDbVersionError;
Defined in: packages/common/src/local-first/Evolu.ts:1021
Represents app-level errors that can occur in Evolu.
Apps show them from EvoluErrorDep.evoluError. Problems a relay causes while syncing an owner are not EvoluErrors; see below. An unexpected failure while syncing is an UnknownError.
An error that leaves the app unusable deserves a modal dialog, which moves
focus into itself and restores it when closed. Any other error is a status
message: show it in a region with role="alert", which screen readers
announce without moving focus, so the user keeps working and a background tab
shows it when the user returns. Avoid alert(), which blocks the page, once
in every open tab.
- UnsupportedDbVersionError blocks the app: the local data needs a newer version of it. Ask the user to update the app or close all its tabs.
- DatabaseHeldError blocks the app: another context keeps holding the local data, as a browser can until it restarts. Ask the user to close the app's other tabs or to restart the browser, then to reload the app.
- OtherBuildRunningError blocks the app while it lasts: another version of the app holds the local data. Ask the user to close the app's other tabs. It clears when the wait ends.
- UnknownError blocks the app: Evolu is in an unknown state after an unexpected failure, such as a mutation that could not be stored or a database whose worker failed. Ask the user to close all its tabs.
A problem syncing an owner through a relay belongs to that relay and often
repeats in every round, so sync state shows it on the relay's route, as its
PendingSyncRoute.failure with its details, and apps show it as the
owner's Error OwnerSyncStatus. When the relay rejected or failed a
request, or sent a frame that could not be decoded, the route shows a
ProtocolError. A ProtocolQuotaError needs more relay quota,
then Evolu.requestSync, and a ProtocolVersionError needs an app
or relay update. A route shows an UnknownError failure when this
device could not store received changes, for example on a full disk.
A received change that was not created with the owner's encryption key, was
altered afterwards, or cannot be decoded by this app version is skipped,
while everything else still syncs. The relay offers it again in every round,
so the route shows it as its skippedError: the
DecryptWithXChaCha20Poly1305Error,
ProtocolTimestampMismatchError, or ProtocolInvalidDataError of
the first change skipped in a reply, with its details. The owner's status is
Error with it too, unless a relay has a failure. Once this database stores
a valid change with that timestamp, for example from another relay, the relay
no longer offers its copy, and the route completes with its next sync, such
as after a reconnect or Evolu.requestSync, during which no changes
arrive from other relays. If you don't trust that relay, stop using it for
the owner. For owners that use the default transports, such as
Evolu.appOwner when EvoluConfig.transports is not empty,
replace the relay there; an empty list stops syncing the app owner and makes
Evolu.useOwner require explicit transports. For an owner you passed
explicit transports to Evolu.useOwner, call its UnuseOwner and
use it again without that relay. Do this wherever the owner is used, such as
in every tab, because the owner syncs through every transport any of its uses
claims. If every route of the owner shows
DecryptWithXChaCha20Poly1305Error and your code creates or shares the
owner, check the owner's keys.
A ProtocolChangeTooLargeError skip is a change no protocol message can hold: one this device saved before maxMutationSize existed, or a crafted one received from a relay. Every route through a relay that lacks it shows it after each sync, and everything else still syncs, but changes received from one relay reach the others only after a reconnect or Evolu.requestSync. The change is not recovered, and replacing relays does not help.