[API reference](https://evolu.dev/docs/api-reference) › [@evolu/common](https://evolu.dev/docs/api-reference/common) › [local‑first/Evolu](https://evolu.dev/docs/api-reference/common/local-first/Evolu) › EvoluError

```ts
type EvoluError =
  | DatabaseHeldError
  | OtherBuildRunningError
  | UnknownError
  | UnsupportedDbVersionError;
```

Defined in: [packages/common/src/local-first/Evolu.ts:1021](https://github.com/evoluhq/evolu/blob/bb2644275dd99ff6dce4744db578967699045ea3/packages/common/src/local-first/Evolu.ts#L1021)

Represents app-level errors that can occur in [Evolu](https://evolu.dev/docs/api-reference/common/local-first/Evolu/interfaces/Evolu).

Apps show them from [EvoluErrorDep.evoluError](https://evolu.dev/docs/api-reference/common/local-first/Evolu/interfaces/EvoluErrorDep#evoluerror). Problems a relay causes
while syncing an owner are not EvoluErrors; see below. An unexpected failure
while syncing is an [UnknownError](https://evolu.dev/docs/api-reference/common/Error/variables/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](https://evolu.dev/docs/api-reference/common/local-first/Db/interfaces/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](https://evolu.dev/docs/api-reference/common/local-first/Db/interfaces/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](https://evolu.dev/docs/api-reference/common/local-first/Shared/interfaces/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](https://evolu.dev/docs/api-reference/common/Error/variables/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](https://evolu.dev/docs/api-reference/common/local-first/Shared/interfaces/PendingSyncRoute#failure) with its details, and apps show it as the
owner's `Error` [OwnerSyncStatus](https://evolu.dev/docs/api-reference/common/local-first/Shared/type-aliases/OwnerSyncStatus). When the relay rejected or failed a
request, or sent a frame that could not be decoded, the route shows a
[ProtocolError](https://evolu.dev/docs/api-reference/common/local-first/Protocol/type-aliases/ProtocolError). A [ProtocolQuotaError](https://evolu.dev/docs/api-reference/common/local-first/Protocol/interfaces/ProtocolQuotaError) needs more relay quota,
then [Evolu.requestSync](https://evolu.dev/docs/api-reference/common/local-first/Evolu/interfaces/Evolu#requestsync), and a [ProtocolVersionError](https://evolu.dev/docs/api-reference/common/local-first/Protocol/interfaces/ProtocolVersionError) needs an app
or relay update. A route shows an [UnknownError](https://evolu.dev/docs/api-reference/common/Error/variables/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](https://evolu.dev/docs/api-reference/common/Crypto/interfaces/DecryptWithXChaCha20Poly1305Error),
[ProtocolTimestampMismatchError](https://evolu.dev/docs/api-reference/common/local-first/Protocol/interfaces/ProtocolTimestampMismatchError), or [ProtocolInvalidDataError](https://evolu.dev/docs/api-reference/common/local-first/Protocol/interfaces/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](https://evolu.dev/docs/api-reference/common/local-first/Evolu/interfaces/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](https://evolu.dev/docs/api-reference/common/local-first/Evolu/interfaces/Evolu#appowner) when [EvoluConfig.transports](https://evolu.dev/docs/api-reference/common/local-first/Evolu/interfaces/EvoluConfig#transports) is not empty,
replace the relay there; an empty list stops syncing the app owner and makes
[Evolu.useOwner](https://evolu.dev/docs/api-reference/common/local-first/Evolu/interfaces/Evolu#useowner) require explicit transports. For an owner you passed
explicit transports to [Evolu.useOwner](https://evolu.dev/docs/api-reference/common/local-first/Evolu/interfaces/Evolu#useowner), call its [UnuseOwner](https://evolu.dev/docs/api-reference/common/local-first/Evolu/type-aliases/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](https://evolu.dev/docs/api-reference/common/Crypto/interfaces/DecryptWithXChaCha20Poly1305Error) and your code creates or shares the
owner, check the owner's keys.

A [ProtocolChangeTooLargeError](https://evolu.dev/docs/api-reference/common/local-first/Protocol/interfaces/ProtocolChangeTooLargeError) skip is a change no protocol message can
hold: one this device saved before [maxMutationSize](https://evolu.dev/docs/api-reference/common/local-first/Evolu/variables/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](https://evolu.dev/docs/api-reference/common/local-first/Evolu/interfaces/Evolu#requestsync). The change is not recovered, and replacing relays
does not help.