---
title: Errors
description: "relate, the embedded Cypher graph database (relatedb.ai): The errors relate reports, each at a stable anchor, with its message where it is recorded, its cause, remedy, whether a retry helps, and the CLI exit code."
type: reference
surfaces:
  - cli
  - cypher
  - http
  - bolt
  - mcp
  - python
  - agents
status: stable
verified: 0.1.2
verified_by:
  - cli
canonical_url: https://relatedb.ai/docs/reference/errors/
prerequisites: []
related:
  - get-started/agent-quickstart
  - reference/cli/exit-codes-and-errors
  - guides/operate/troubleshooting
last_updated: 2026-11-08
---

# Errors

The errors relate reports, each at a stable anchor, with its message where it is recorded, its cause, remedy, whether a retry helps, and the CLI exit code.

> Verified against relate 0.1.2. If your `relate --version` is newer, read https://relatedb.ai/docs/reference/changelog/#since-0.1.2

Each error relate reports has a stable id, and each id is an anchor on this page: `https://relatedb.ai/docs/reference/errors/#<id>`. A row gives the message pattern as relate prints it, where it is recorded, the cause, the remedy, whether retrying the same statement can succeed, and the CLI exit code. The tables are generated from one data file, so this page and its markdown twin list the same entries.

## Synopsis

On the CLI, a failed statement prints its message on stderr and exits with the [exit code](https://relatedb.ai/docs/reference/glossary/#exit-code) of its class. In `--mode envelope`, `--json` and `--jsonl`, it also prints an [error object](https://relatedb.ai/docs/reference/glossary/#error-object) on stdout. The object's `code` is the class, `kind` is the engine's error variant, `retryable` is `true` for a write-write conflict and for a `--concurrent-logical-workspace-limit` refusal while other statements hold the workspace pool, and `message` repeats the stderr text.

```bash verify
relate --mode envelope 'RETURN $x AS x'
```

The first line of the output is stderr, the second is stdout:

```text
semantic error: ParameterMissing: Expected parameter(s): x
{"error":{"code":"validation_error","exit_code":6,"kind":"semantic","message":"semantic error: ParameterMissing: Expected parameter(s): x","retryable":false}}
```

A syntax error adds `column` and `source`, so a caller can point at the failing token without parsing the message:

```text
syntax error: parse error: expected RightParen, got "RETURN" (RETURN)
  MATCH (n RETURN n
           ^
{"error":{"code":"validation_error","column":10,"exit_code":6,"kind":"syntax","message":"syntax error: parse error: expected RightParen, got \"RETURN\" (RETURN)   MATCH (n RETURN n            ^","retryable":false,"source":"MATCH (n RETURN n"}}
```

`relate agent-context` prints the exit codes of the installed version:

```text
Exit codes:
  0  success: success, including an empty result
  1  fatal_error: runtime failure: store open or I/O error, capacity limit, query execution failure, internal error
  2  usage_error: unknown flag, bad or missing value, extra positional
  5  conflict: write-write conflict, or the store is locked by another opener
  6  validation_error: the statement is rejected: syntax, semantic or type error
  7  timeout: a statement exceeded --timeout
```

In the tables, a message's `<name>` marks a variable part and `…` is an elision in the source. A dash (—) means the sources do not state the value, or it does not apply to that [surface](https://relatedb.ai/docs/reference/glossary/#surface).

## CLI errors

Errors and notices from the `relate` command itself: statement classes, flag and environment checks, and the skill installer.

| Error | Message | Cause | Remedy | Retryable | Exit code |
| --- | --- | --- | --- | --- | --- |
| `cli-validation-error-syntax`; code `validation_error`, kind `syntax`; Neo4j `Neo.ClientError.Statement.SyntaxError`; HTTP 400; Python `ProgrammingError` | `syntax error: parse error: unexpected token "<token>"` | The statement does not parse. The error object adds `column` and `source` when the parser reports a position. Another recorded form: `syntax error: parse error: expected RightParen, got "RETURN" (RETURN)`. The stderr form adds the source line and a caret under the column. | Fix the statement at the reported column; a did-you-mean line follows when the first word is close to a command name. | no | 6 |
| `cli-validation-error-semantic`; code `validation_error`, kind `semantic`; Neo4j `Neo.ClientError.Statement.SemanticError`; Python `OperationalError` | `semantic error: <detail>` | The statement parses but is rejected before it runs: a missing parameter, an unknown namespace, a write on a read-only open, and similar. | Read the detail after `semantic error:`; the typed engine errors (ParameterMissing, DatabaseNotFound and others) have their own entries. | no | 6 |
| `cli-validation-error-argument`; code `validation_error`, kind `argument`; Neo4j `Neo.ClientError.General.InvalidArguments`; Python `DataError` | — | An argument value is rejected, for example a DDL `OPTIONS`/`indexConfig` value. Recorded form: `semantic error: NumberOutOfRange` for a negative vector dimension; the prefix is `semantic error:` although the kind is `argument`. On Bolt the same rejection arrives at RUN as FAILURE `Neo.ClientError.General.InvalidArguments` with message `semantic error: NumberOutOfRange`. | Correct the rejected value. | no | 6 |
| `cli-validation-error-type`; code `validation_error`, kind `type`; GQL status `22G03`; Neo4j `Neo.ClientError.Statement.TypeError`; HTTP 400; Python `DataError` | `type error: <detail>` | A value has the wrong type for the operation. | Convert or check the value's type in the statement. | no | 6 |
| `cli-fatal-error-execution`; code `fatal_error`, kind `execution` | — | A query execution failure discovered while producing rows. | Read the message; execution failures are not retryable. | no | 1 |
| `cli-conflict-conflict`; code `conflict`, kind `conflict`; Neo4j `Neo.TransientError.Transaction.Outdated` | `write-write conflict` | Two transactions wrote the same data; the later one lost. The Java, Go and Swift clients report the conflict from `commit()` with code `Neo.TransientError.Transaction.Outdated`, GQL status `42000`, stage runtime, retryable true (Java `TransientException`). | Re-run the statement in a fresh transaction. One of the two retryable errors; the other is a contended workspace-pool refusal. | yes | 5 |
| `cli-conflict-locked`; code `conflict`, kind `locked`; Neo4j `Neo.DatabaseError.General.UnknownError` | `storage locked: <path>` | Another process holds the store: a persistent store takes exclusive ownership of its directory and WAL, or its `.rl` file, at open. The error object's `message` is `storage locked: <path>`; stderr prints `Failed to open Relate: storage locked: <path>`. A `--read-only` open of a `.rl` file is refused the same way while a writer holds it. For a directory store, `<path>` is the writer lock file inside it. `relate serve` on a store another process holds stops at startup with `Error: Failed to open Relate: storage locked: <path>` and exit code 1, not 5 ([cli-serve-open-failed](https://relatedb.ai/docs/reference/errors/#cli-serve-open-failed)); `relate clone` of a held `.rl` source exits 1 too ([cli-clone-locked](https://relatedb.ai/docs/reference/errors/#cli-clone-locked)). | Close the other opener, or open with `--read-only` (a directory store can be read beside its writer; a `.rl` file only while no writer holds it). Not retryable until the other opener exits. | no | 5 |
| `cli-clone-locked` | `Failed to clone database: storage locked: <path>` | `relate clone` with a `.rl` source while another process holds it open for writing; no error object is printed. | Wait for the writer to exit, or clone a directory store, which can be cloned while its writer runs. | — | 1 |
| `cli-serve-open-failed` | `Error: Failed to open Relate: <detail>` | `relate serve` could not open its store: another process holds it (`storage locked: <path>`), or a `--read-only` open names a store that does not exist. It stops at startup; no error object is printed. The query run reports the same lock with exit code 5 ([cli-conflict-locked](https://relatedb.ai/docs/reference/errors/#cli-conflict-locked)); `relate serve` exits 1. | Stop the other opener, or serve a directory store `--read-only` beside its writer; check the `--database` path. | — | 1 |
| `cli-fatal-error-capacity`; code `fatal_error`, kind `capacity`; Neo4j `Neo.ClientError.General.TransactionOutOfMemoryError`; HTTP 507; Python `DataError` | `capacity exceeded: used=… limit=…` | A memory or capacity limit refused the work: the `--logical-graph-size-limit` cap, the per-allocation expression cap, or the 64 MiB per-record WAL payload cap. | Raise the named limit, or commit the data in smaller transactions. | no | 1 |
| `cli-fatal-error-resource`; code `fatal_error`, kind `resource` | `resource limit exceeded: concurrent-logical-workspace-limit limit=<bytes>` | The statement needs more shared workspace than `--concurrent-logical-workspace-limit` allows. | Retry when fewer statements run, or raise `--concurrent-logical-workspace-limit`. | no | 1 |
| `cli-fatal-error-storage`; code `fatal_error`, kind `storage`; Neo4j `Neo.DatabaseError.General.UnknownError` | `storage error: <detail>` | A storage failure, for example a corrupt snapshot or an unsupported stored value encoding at open. Recorded forms: `storage error: database not found: <path>` (a missing `.rl`), `storage error: read-only open requires an existing database at <path>` (a missing or empty directory), `storage error: read-only open requires an existing WAL at <path>/wal` (a directory store without its WAL folder), `storage error: snapshot codec mismatch: directory is <codec>, requested <codec>` (`--snapshot-format` against an existing store), `storage error: wal_dir is not supported for .rl single-file databases …` (`--wal-dir` with a `.rl` store; nothing is created), and `storage error: unsupported snapshot version <n>` (a store written by a newer relate; `relate info` prints `Failed to read store info: storage error: unsupported snapshot version <n>`). Also seen: `storage error: WAL checksum mismatch` (a damaged WAL record before the tail; `--read-only` and `relate clone` fail the same way, clone prefixed `Failed to clone database: `) and `storage error: unsupported graph value encoding: <n>` (JSON). stderr prefixes `Failed to open Relate: `. | Restore from a backup clone; do not copy a snapshot without its WAL. | no | 1 |
| `cli-unsupported-uri-scheme`; code `fatal_error`, kind `storage`; Python `OperationalError` | `storage error: unsupported URI scheme <scheme>:// (engine URIs are :memory:, a filesystem path, or file://)` | `--database` was given a URL such as `bolt://` or `neo4j://`; a store is a path or `:memory:`. stderr prefixes `Failed to open Relate: `. | Open a path, or serve the store with `relate serve --bolt <port> --database <path> --read-only`. | no | 1 |
| `cli-live-freshness-unsupported`; code `fatal_error`, kind `semantic` | `semantic error: live freshness (WAL follow) is only supported for native directory databases` | `--read-only=live` on a `.rl` store or `:memory:`; only a directory store has a WAL to follow. stderr prefixes `Failed to open Relate: `. | Use `--read-only` (a snapshot at open), or a directory store. | no | 1 |
| `cli-fatal-error-io`; code `fatal_error`, kind `io`; Neo4j `Neo.DatabaseError.General.UnknownError` | — | An operating-system I/O failure, including a full disk. | Check the path, permissions and free space. | no | 1 |
| `cli-fatal-error-internal`; code `fatal_error`, kind `internal`; GQL status `50N42`; Neo4j `Neo.DatabaseError.General.UnknownError`; HTTP 500; Python `InternalError` | `internal error` | An engine invariant failed; not the statement's fault. | Report it with `relate --version` and the statement. | no | 1 |
| `cli-timeout`; code `timeout`, kind `execution` | `Error: query timed out after <duration>` | A statement ran longer than `--timeout`. stderr prints `Error: query timed out after <duration>`; the error object's `message` drops the `Error: ` prefix. `--timeout 0.1` prints as `100ms`. | Bound the work with `LIMIT` or a narrower pattern, or raise `--timeout`. | no | 7 |
| `cli-usage-error`; code `usage_error` | `Error: unknown flag: <flag>` | A parser usage error: unknown flag, bad or missing value, extra positional. stderr carries the `Error:` line, the command's `Usage:` line and a `--help` hint; a close match adds `Did you mean '<flag>'?`. An extra positional prints `Error: unexpected argument: <arg>`. | Run `relate <command> --help`. | — | 2 |
| `cli-command-not-included`; code `usage_error` | `Error: the '<command>' command is not included in this build of relate` | The command's feature is not compiled into this build bundle (release binaries are the full bundle). | Use a full build. | — | 2 |
| `cli-invalid-param`; code `usage_error` | `Error: invalid --param value: parameter <name>: …` | A `--param` value that looks like JSON does not parse, is a non-finite number, or is an integer above i64::MAX. | Quote JSON values; JSON-quote a date that starts with digits. | — | 2 |
| `cli-fetch-params-failed` | `Error: --fetch-params <name>: <detail>` | A `--fetch-params` source could not be read or fetched, is over the 64 MiB cap, or is not JSON; nothing runs, and no error object is printed. Recorded forms: `Error: --fetch-params <name>: invalid JSON: <detail>` and `Error: --fetch-params <name>: reading <path>: <reason>` (for example `No such file or directory (os error 2)`, or `source exceeded the 64 MiB cap`). A value without `=` is a usage error instead: `Error: invalid --fetch-params value: expected name=value`, exit code 2. An HTTP source that answers an error status prints `Error: --fetch-params <name>: HTTP <status>` (observed as HTTP 404). | Check the path or URL and that the source is one JSON document. | — | 1 |
| `cli-invalid-namespace`; code `usage_error` | `Error: invalid --namespace: unknown namespace '<name>' (expected neo4j, system or system_ontologies)` | `--namespace` names something other than the three fixed namespaces. | Use `neo4j`, `system` or `system_ontologies`. | — | 2 |
| `cli-pull-namespace`; code `usage_error` | `Error: --namespace is not valid with pull (pull always writes the neo4j namespace)` | `--namespace` placed before the `pull` verb. | Drop `--namespace`; pull always writes `neo4j`. | — | 2 |
| `cli-invalid-env-max-rows`; code `usage_error` | `Error: invalid RELATE_MAX_ROWS: '<value>' is not a non-negative integer` | `RELATE_MAX_ROWS` is not a non-negative integer. | Set an integer; `0` is unlimited. | — | 2 |
| `cli-invalid-env-agent-mode`; code `usage_error` | `Error: invalid RELATE_AGENT_MODE: '<value>' is neither 1 nor 0` | `RELATE_AGENT_MODE` is not `1` or `0`. | Set `1` or `0`, or unset it. | — | 2 |
| `cli-invalid-env-durability-mode`; code `usage_error` | `Error: invalid RELATE_DURABILITY_MODE: semantic error: invalid durability mode "<value>"; expected full, everysecond, or snapshot` | `RELATE_DURABILITY_MODE` is not `full`, `everysecond` or `snapshot`. | Use one of the three values. | — | 2 |
| `cli-invalid-env-safe-mode`; code `usage_error` | `Error: invalid RELATE_SAFE_MODE: '<v>' is not 1 or 0` | `RELATE_SAFE_MODE` is not `1` or `0`. | Set `1` or `0`, or unset it. | — | 2 |
| `cli-safe-remote-load`; code `usage_error` | `Error: --safe refuses a remote --load source — a downloaded store is untrusted input, so safe mode introduces none …` | `--safe` (or `RELATE_SAFE_MODE=1`) with an `https://` `--load` source, on the query run or on `relate serve`; refused before any network request. The binary ends the message with an upstream reference in parentheses. | Download the file, check its SHA-256, and pass the local path to `--load`; or drop `--safe`. | — | 2 |
| `cli-load-plain-http`; code `usage_error` | `Error: invalid --load: plain http:// is only allowed for a loopback host; use https://<rest>` | A `--load` URL uses plain `http://` for a host other than a loopback address. | Use the `https://` URL the message names, or a local file. | — | 2 |
| `cli-invalid-env-logical-graph-size-limit`; code `usage_error` | `Error: invalid RELATE_LOGICAL_GRAPH_SIZE_LIMIT: semantic error: invalid memory limit '<value>'` | The value does not parse as a size. | Use bytes or mb/mib/gb/gib; `0` is unlimited. | — | 2 |
| `cli-invalid-env-expression-memory-limit`; code `usage_error` | `Error: invalid RELATE_EXPRESSION_MEMORY_LIMIT: invalid memory limit '<value>'` | The value does not parse as a size. | Use a size, or `none`. | — | 2 |
| `cli-invalid-env-concurrent-logical-workspace-limit`; code `usage_error` | `Error: invalid RELATE_CONCURRENT_LOGICAL_WORKSPACE_LIMIT: must be positive` | The variable is `0`; a value that does not parse prints `Error: invalid RELATE_CONCURRENT_LOGICAL_WORKSPACE_LIMIT: invalid memory limit '<value>'` instead. | Use a positive size, or unset it to leave admission off. | — | 2 |
| `cli-invalid-env-max-traversal-depth`; code `usage_error` | `Error: invalid RELATE_MAX_TRAVERSAL_DEPTH: must be between 1 and 2000` | `0` or a value over 2000; a non-integer prints `Error: invalid RELATE_MAX_TRAVERSAL_DEPTH: '<value>' is not a number` instead. | Use an integer from 1 to 2000. | — | 2 |
| `cli-invalid-env-preview`; code `fatal_error`, kind `semantic` | `Failed to open Relate: semantic error: SemanticError: invalid RELATE_PREVIEW value: unknown preview feature '<name>' (known features: …)` | `RELATE_PREVIEW` names a feature the engine does not know; the open fails closed. The error object's `message` drops the `Failed to open Relate: ` prefix. | Use a name from the known-features list in the message. | — | 1 |
| `cli-invalid-env-pattern-engine`; code `fatal_error`, kind `semantic` | `semantic error: invalid RELATE_PATTERN_ENGINE: semantic error: invalid pattern engine "<value>"; expected auto, nfa, or walk` | `RELATE_PATTERN_ENGINE` is not `auto`, `nfa` or `walk`; the open fails. stderr prefixes `Failed to open Relate: `. | Use one of the three values, or unset it. | no | 1 |
| `cli-invalid-env-bulk-batch-threshold`; code `fatal_error`, kind `semantic` | `semantic error: invalid RELATE_BULK_BATCH_THRESHOLD '<value>'` | `RELATE_BULK_BATCH_THRESHOLD` is not a number; the open fails. stderr prefixes `Failed to open Relate: `. | Set a whole number, or unset it. | no | 1 |
| `cli-invalid-env-snapshot-format`; code `fatal_error`, kind `storage` | `storage error: unknown snapshot codec '<value>' (expected parquet, json, markdown or rkyv)` | `RELATE_SNAPSHOT_FORMAT` names no codec the variable takes (`parquet-wide` is a flag value only); a query run's open fails, `:memory:` included. stderr prefixes `Failed to open Relate: `. The same value given as `--snapshot-format` is a usage error, exit code 2: `Error: invalid --snapshot-format: storage error: unknown snapshot format '<value>' (expected parquet or json or markdown or parquet-wide)`. `rkyv` is not compiled into the release binary: `RELATE_SNAPSHOT_FORMAT=rkyv` fails the open with `storage error: rkyv snapshot codec is not compiled into this build (enable the "rkyv-codec" feature)`. | Use `parquet`, `json` or `markdown`, or unset it; for wide-column parquet, pass `--snapshot-format parquet-wide`. | no | 1 |
| `cli-final-checkpoint-failed`; code `fatal_error` | `Error: final checkpoint failed: <reason>` | The checkpoint every persistent run takes on exit failed, for example on a full disk. A non-zero statement exit code is kept instead. | Free disk space and check permissions. | — | 1 |
| `cli-open-transaction-at-exit` | `Warning: exiting with an open transaction; rolling back uncommitted changes. Use .commit before exiting to persist them.` | A `.begin` transaction was still open at exit. One-shot and piped runs exit 1; the interactive shell keeps exit 0. | End the script with `.commit` (or `.rollback`). | — | 1 |
| `cli-stdin-read-error` | `Error: could not read query input from stdin: <reason>` | Piped stdin could not be read, including invalid UTF-8; nothing runs. | Pipe valid UTF-8. | — | 1 |
| `cli-load-csv-unavailable`; code `fatal_error`, kind `execution` | `LOAD CSV file unavailable` | A `LOAD CSV` path escapes the configured root, is a symlink escape or a special file, does not exist, or local files are denied (no `--load-csv-dir`). | Pass `--load-csv-dir <dir>` and keep files under it. | no | 1 |
| `cli-load-csv-byte-limit`; code `fatal_error`, kind `execution` | `LOAD CSV file exceeds byte limit` | The CSV file is over 8,388,608 bytes. | Split the file; the limit cannot be raised from the CLI. | no | 1 |
| `cli-load-csv-invalid-configuration`; code `fatal_error`, kind `semantic` | `semantic error: LOAD CSV invalid configuration` | The directory given to `--load-csv-dir` (or `RELATE_LOAD_CSV_DIR`) does not exist or is not a directory; the open fails. stderr prefixes `Failed to open Relate: `. | Create the directory first, or correct the path. | no | 1 |
| `cli-parquet-not-compiled` | `parquet snapshot codec is not compiled into this build (enable the "parquet" feature)` | `--snapshot-format parquet` in a build without the parquet feature. | Use `--snapshot-format json`, or a full build. | — | — |
| `cli-skill-refusing-to-touch` | `Error: skill: refusing to touch <dest>: no .relate-installed marker present (directory was not created by relate); pass --force to override` | The skills destination exists and was not written by relate. | Move the directory, or pass `--force` to overwrite it. | — | 1 |
| `cli-skill-unknown-agent` | `Error: skill: unknown agent: '<name>'` | `--agent` names an agent the CLI does not know; a second line lists the valid agents. | Use a name from the `valid agents:` line. | — | 2 |
| `cli-skill-no-agents` | `Error: skill: no supported agents detected` | A `relate skill` action ran without `--agent` and none of the agents' configuration directories exists in the home directory; a second line lists the valid agents. | Pass `--agent <name>` with a name from the `valid agents:` line. | — | 1 |
| `cli-row-cap-warning`; severity warning | `warning: result truncated to 100 rows (the statement returned 250); pass --max-rows 0 for all rows` | Not an error. The row cap cut the printed rows (100 by default under a detected agent harness with stdout not a terminal). The counts in the message vary. | Pass `--max-rows 0` for all rows, or bound the work with `LIMIT`. | — | 0 |
| `cli-write-changed-nothing`; severity notice | `note: write statement changed nothing; the graph is unchanged` | Not an error. A write statement applied nothing, often because a zero-row `MATCH` short-circuited it. In a script the note names the statement (`note: write statement 2 of 3 changed nothing; …`), and a transaction that persisted nothing prints `note: .commit changed nothing; the transaction applied no changes`. | Grep stderr for the prefix `note: write statement`; the exit code stays 0. | — | 0 |
| `cli-serve-nothing-to-serve`; code `usage_error` | `Error: serve has nothing to serve: pass --http PORT and/or --mcp PORT\|stdio and/or --bolt PORT` | `relate serve` with no listener flag; ports have no defaults. | Pass at least one of `--http PORT`, `--mcp PORT\|stdio` or `--bolt PORT`. | — | 2 |
| `cli-serve-read-only-before-verb`; code `usage_error` | `Error: serve takes --read-only after the verb, not before it (relate serve --read-only …)` | `--read-only` placed before the `serve` word. | Put `--read-only` after `serve`. | — | 2 |
| `cli-serve-auth-malformed` | `Error: --auth: expected user:password or 'none'` | `--auth` has no colon. | Pass `<user>:<password>` or `none`. | — | 1 |
| `cli-serve-env-auth-malformed` | `Error: RELATE_AUTH: expected user:password or 'none'` | `RELATE_AUTH` has no colon. | Set `RELATE_AUTH` to `<user>:<password>` or `none`. | — | 1 |
| `cli-serve-env-auth-empty-side` | `Error: RELATE_AUTH: expected user:password with both sides non-empty` | `RELATE_AUTH` has an empty user or password. | Set both sides of `RELATE_AUTH`. | — | 1 |
| `cli-serve-auth-missing-value`; code `usage_error` | `Error: --auth requires USER:PASSWORD or none` | `--auth` is the last argument, with no value. | Pass `--auth <user>:<password>` or `--auth none`. | — | 2 |
| `cli-serve-auth-stdio`; code `usage_error` | `Error: serve --mcp stdio skips auth (the host spawned the process, ADR-0232); --auth applies to the --http PORT/--mcp PORT/--bolt listeners only` | `--auth` with `--mcp stdio` as the only listener; the stdio transport has no credential. | Drop `--auth`, or add an HTTP, MCP-over-HTTP or Bolt listener for it to guard. | — | 2 |
| `cli-serve-bind-failed` | `Error: serve --<surface> <port>: cannot bind <host>:<port>: <reason>` | Another process listens on the port, or the address is not available on this machine. On macOS the reason reads `Address already in use (os error 48)`; the OS error number differs by platform. | Choose a free port, or stop the process that holds it. | — | 1 |
| `cli-open-readonly-missing-dir` | `Failed to open Relate: storage error: read-only open requires an existing database at <path>` | `--read-only` on a directory path that holds no store; a read-only open never creates one. | Correct the path, or create the store with a writable open first. | — | 1 |
| `cli-open-readonly-missing-rl` | `Failed to open Relate: storage error: database not found: <path>` | `--read-only` on a `.rl` path that does not exist; a read-only open never creates one. | Correct the path, or create the store with a writable open first. | — | 1 |
| `cli-clone-wal-dir-rl` | `Failed to clone database: storage error: wal_dir is not supported for .rl single-file databases (ADR-0074)` | `relate clone --wal-dir` with a `.rl` source, which holds its own WAL. | Drop `--wal-dir`; it applies to a directory source only. | — | 1 |
| `cli-clone-markdown-body-properties-codec` | `Failed to clone database: semantic error: markdown body properties are set but the store's snapshot codec is parquet, not markdown; the configuration would be ignored` | `--markdown-body-properties` on a clone whose destination codec is not `markdown`. | Add `--to-snapshot-format markdown`, or drop `--markdown-body-properties`. | — | 1 |
| `cli-clone-source-missing-rl` | `Failed to clone database: storage error: database not found: <path>` | The `.rl` SOURCE does not exist. | Correct the SOURCE path. | — | 1 |
| `cli-info-not-found` | `Failed to read store info: storage error: database not found: <path>` | `relate info --database` names a path with no store. | Correct the path. | — | 1 |
| `cli-telemetry-no-config-dir` | `Error: telemetry: cannot resolve a config directory (set $XDG_CONFIG_HOME, $HOME, $APPDATA, or $USERPROFILE)` | `relate telemetry on` or `off` with no config directory base: no absolute `XDG_CONFIG_HOME`, no `HOME`, and no absolute `APPDATA` or `USERPROFILE`, so there is nowhere to write its config file. A failed write prints `Error: telemetry: writing <path>: <reason>` (from the source; not reproduced). | Set `HOME`, or set `XDG_CONFIG_HOME` to an absolute path; `DO_NOT_TRACK=1` turns usage metrics off without a config directory. | — | 1 |
| `cli-pull-destination-not-empty` | `Error: destination database is not empty; pull writes into an empty database only (ADR-0158)` | `relate pull` into a store that already holds data. The check runs before any connection. | Pull into a new path; a pull never merges. | — | 1 |
| `cli-pull-shape-query` | `Error: shape query RETURN must be graph elements (nodes/rels/paths), not projections/scalars/aggregates; rejected item: <item>` | A `--query` statement returns a property, a scalar or an aggregate; pull copies only nodes, relationships and paths. | Return the graph elements themselves, such as `RETURN n`. | — | 1 |
| `cli-pull-plaintext` | `Error: refusing to send Basic auth credentials in the clear: Query API URL <url> is http:// to a non-loopback host; pass --allow-plaintext to accept the risk, or use an https:// NEO4J_URI` | The Neo4j URI resolves to `http://` on a host other than the loopback interface, so the credentials would cross the network unencrypted. | Use an `https://` `NEO4J_URI`, or pass `--allow-plaintext` to accept the risk. | — | 1 |
| `cli-pull-memory`; code `usage_error` | `Error: pull cannot target :memory: (--database must persist)` | `relate pull --database :memory:`; the copy would vanish when the command exits. | Name a directory or `.rl` path. | — | 2 |
| `cli-pull-credential-missing` | `Error: <name> missing from environment` | No `--from` env file, and a Neo4j variable the pull needs is not set. | Set `NEO4J_URI`, `NEO4J_USERNAME` and `NEO4J_PASSWORD`, or name an env file with `--from`. | — | 1 |
| `cli-pull-env-file-key` | `Error: <name> missing from env file` | The `--from` env file lacks one of `NEO4J_URI`, `NEO4J_USERNAME` or `NEO4J_PASSWORD`. No store is created. | Add the key to the env file. | — | 1 |
| `cli-query-no-statements` | `Error: no statements in --query value` | `relate pull` or `relate push` got a `--query` value with no statement in it. | Pass at least one statement. | — | 1 |
| `cli-push-one-scope`; code `usage_error` | `Error: push takes one of --query, --labels, or --types (none pushes the whole store)` | More than one of `--query`, `--labels` and `--types`. | Pass one selector, or none to push the whole store. | — | 2 |
| `cli-push-namespace`; code `usage_error` | `Error: --namespace is not valid with push (push always reads the neo4j namespace)` | `--namespace` with `relate push`. | Drop `--namespace`. | — | 2 |
| `cli-push-merge-key-format`; code `usage_error` | `Error: --merge-key "<value>" must be NAME:PROP[,PROP] (no ':' found)` | A `--merge-key` value without a colon. | Pass `<Label>:<property>[,<property>]`. | — | 2 |
| `cli-run-not-installed`; code `usage_error` | `Error: no installed action '<name>' — first-party extension available: relate extension install <name>` | `relate run <name>` for a first-party extension that is not installed. | Install it with `relate extension install <name>`. | — | 2 |
| `cli-run-no-action`; code `usage_error` | `Error: run requires an action name (no actions installed; relate extension install <name> adds one)` | `relate run` with no action name. | Name an installed action; `relate run --help` lists them. | — | 2 |
| `cli-extension-url-scheme` | `Error: extension install: --url accepts only https URLs (or plain http to the loopback interface); '<url>' is neither` | `relate extension install --url` with a plain `http://` URL to another host. | Use an `https://` URL. | — | 2 |
| `cli-extension-remove-not-installed` | `Error: extension remove: no installed extension '<name>' (relate extension list prints the installed set)` | `relate extension remove` for a name that is not installed. | Check the name with `relate extension list`. | — | 1 |
| `cli-extension-init-exists` | `Error: extension init: <dir> already exists (init writes a new package directory)` | `relate extension init <name>` where a directory of that name exists. | Choose another name, or move the directory. | — | 1 |
| `cli-extension-check-not-executable` | `executable: failed: the extension executable <path> is not executable` | `relate extension check` on a package whose executable file lacks the execute bit. | `chmod +x` the executable the manifest names. | — | 2 |
| `cli-extension-child-exited` | `Error: the extension child exited with <n>: <stderr>` | The extension's executable exited before it finished the import. | Read the child's stderr in the message; run `relate extension check` on the package. | — | 1 |
| `cli-extension-no-request` | `Error: the extension wrote no MCP request within 10s` | The extension's executable started but sent nothing for ten seconds. | Check that the executable starts the protocol client; `relate extension check` runs the same handshake. | — | 1 |
| `cli-unknown-dot-command` | `Error: unknown command <name>` | A line starting with a dot that is not a shell dot command. In a script, it stops the run. | Use a listed dot command (`.help` prints them), or an output flag such as `--mode csv` in place of `.mode`. | — | 1 |
| `cli-invalid-mode`; code `usage_error` | `Error: invalid mode '<name>' (expected one of: table, csv, json, jsonl, envelope, markdown, cypher, toon, speedscope)` | `--mode` names no output mode. | Use one of the listed modes. | — | 2 |
| `cli-invalid-width`; code `usage_error` | `Error: invalid --width: a width under 20 columns cannot hold a table; omit --width for the terminal default` | `--width` below 20. | Pass 20 or more, or omit `--width`. | — | 2 |
| `cli-speedscope-requires-profile` | `speedscope mode requires a PROFILE statement: per-operator times are what it exports (the statement carries no plan tree)` | `--mode speedscope` on a statement that is not a `PROFILE`. The statement has already run, and its writes are committed, so rerunning a write duplicates it. A variant ends `(the plan tree carries no PROFILE metrics)`; on 0.16.1 it appears for a `PROFILE` of `count()` over an Expand, such as `MATCH (p:Person)-[:WORKS_ON]->(proj:Project) RETURN count(p)`. No error object is printed. | Prefix the statement with `PROFILE`, or use another mode. | — | 1 |
| `cli-invalid-env-markdown-body-properties` | `Failed to open Relate: semantic error: invalid markdown body properties '<value>': <detail>` | `RELATE_MARKDOWN_BODY_PROPERTIES` (or `--markdown-body-properties`) does not parse. | Use a comma-separated property list, or `Label=LIST` entries separated by `;`. | — | 1 |
| `cli-retired-env` | `Failed to open Relate: semantic error: <name> is set but ignored; set <new name>` | A retired variable is set: `RELATE_MEMORY_LIMIT` (now `RELATE_LOGICAL_GRAPH_SIZE_LIMIT`), `RELATE_TOKEN_ADMISSION` or `RELATE_CONCURRENT_PEAK_TOKEN_LIMIT` (now `RELATE_CONCURRENT_LOGICAL_WORKSPACE_LIMIT`). | Unset it, and set the variable the message names. | — | 1 |
| `cli-retired-cypherlite-env` | `Error: semantic error: <name> is set but ignored; set <new name>` | A `CYPHERLITE_*` variable from before the rename is set to a non-empty value. Every command fails, `--help` and `--version` included. | Unset it, and set the `RELATE_*` variable the message names. | — | 1 |
| `cli-invalid-env-shard-target-bytes` | `Error: final checkpoint failed: storage error: RELATE_SHARD_TARGET_BYTES must be an integer in 1..=1073741824` | `RELATE_SHARD_TARGET_BYTES` is empty, not an integer, or out of range. It is read at a checkpoint that writes Parquet shards, after the run's statements have committed to the WAL, so they are not lost and not to be rerun. | Unset it, or set an integer from 1 to 1073741824, then reopen the store; the next checkpoint writes the snapshot. | — | 1 |
| `cli-line-editor-unavailable` | `warning: line editor unavailable (<reason>); falling back to plain stdin` | The interactive shell could not start its line editor; the shell still runs, without history or editing. | None needed; the shell reads plain lines. | — | — |
| `cli-invalid-fetch-params`; code `usage_error` | `Error: invalid --fetch-params value: <detail>` | A `--fetch-params` value with no source, no parameter name, or a source that is not an `http`, `https` or file path. Recorded details: `missing source`, `missing parameter name`, `unsupported source (only http, https, and file paths): <source>`. | Pass `name=<path or URL>`. | — | 2 |

## Engine errors

Errors the engine raises on every surface. The CLI prints them inside the class prefix of its row (`semantic error:`, `syntax error:`, `type error:`).

| Error | Message | Cause | Remedy | Retryable | Exit code |
| --- | --- | --- | --- | --- | --- |
| `engine-parameter-missing`; code `validation_error`, kind `semantic`; GQL status `42N02`; Neo4j `Neo.ClientError.Statement.ParameterMissing`; HTTP 400; Python `ProgrammingError` | `semantic error: ParameterMissing: Expected parameter(s): <names>` | The statement references a parameter that was not supplied; it is never bound as null. | Bind every referenced parameter (`--param N=V`, or the params map of the client). | no | 6 |
| `engine-database-not-found`; code `validation_error`, kind `semantic`; GQL status `42N00`; Neo4j `Neo.ClientError.Database.DatabaseNotFound`; HTTP 404; Python `OperationalError` | `semantic error: DatabaseNotFound: Graph not found: <name>` | A session namespace or a `USE` target is not one of `neo4j`, `system`, `system_ontologies`. Bolt sends the live Community Edition wire status 42001 with a 42N00 cause. | Use one of the three fixed namespaces. | no | 6 |
| `engine-storage-locked`; GQL status `42000`; Neo4j `Neo.DatabaseError.General.UnknownError`; Python `OperationalError` | `storage locked: <path>` | Another process holds the store for writing when a client opens it: `relate.connect(path)` in Python, `Database.open(path)` in Node.js. Python raises `OperationalError` with kind `StorageError` and this message. The Node.js client (@relate/relate 0.16.1) reports every `Database.open` failure, this one, a missing store and a `{ readOnly: true }` open of a `.rl` store a writable handle holds included, as `RelateError` with message `internal error`, code `Neo.DatabaseError.General.UnknownError`, stage `internal` and `gqlStatus` `42000`. The CLI reports the lock as [cli-conflict-locked](https://relatedb.ai/docs/reference/errors/#cli-conflict-locked). The Java, Go and Swift clients report the same: `DatabaseException` (Java), `*relate.Error` (Go) or `RelateError.engine` (Swift) with message `internal error`, code `Neo.DatabaseError.General.UnknownError`, GQL status `42000`, stage internal, for a locked store, a second writable open in the same process, and a read-only open of a missing path. | Close the other opener, or open a directory store read-only beside its writer. | no | — |
| `engine-undefined-variable`; code `validation_error`, kind `syntax`; Neo4j `Neo.ClientError.Statement.SyntaxError`; Python `ProgrammingError` | `syntax error: UndefinedVariable: variable '<name>' not defined` | A variable has no binding in scope; an unbound variable never evaluates to null. | Bind the variable in an earlier clause or carry it through `WITH`. | no | 6 |
| `engine-division-by-zero`; code `validation_error`, kind `type`; GQL status `22G03`; Neo4j `Neo.ClientError.Statement.ArithmeticError`; HTTP 400 | `type error: / by zero` | Integer division by zero. Modulo by zero renders `% by zero`. | Guard the divisor. | no | 6 |
| `engine-rounding-necessary`; code `fatal_error`, kind `execution`; Neo4j `Neo.ClientError.Statement.ArithmeticError` | `ArithmeticError: rounding necessary` | `round(x, p, 'UNNECESSARY')` on a value that needs rounding. | Use another rounding mode. | no | 1 |
| `engine-cancelled`; Neo4j `Neo.ClientError.Transaction.TransactionTimedOut` | `query cancelled` | The statement was stopped through its cancel token, for example when the Bolt `--query-timeout-secs` bound expired. | Bound the work, or raise the timeout. | — | — |
| `engine-wal-payload-cap`; code `fatal_error`, kind `capacity`; Neo4j `Neo.ClientError.General.TransactionOutOfMemoryError`; HTTP 507; Python `DataError` | `This statement tried to commit a single WAL record of at least <used>. This is a safety limit protecting against memory exhaustion — the per-record WAL payload cap is <limit>; commit the data in smaller transactions.` | A single commit record is over the 64 MiB per-record WAL payload cap; nothing is written. The message writes the 64 MiB (67,108,864-byte) cap as `64 MB`. | Commit the data in smaller transactions. | no | 1 |
| `engine-graph-size-cap`; code `fatal_error`, kind `capacity`; Neo4j `Neo.ClientError.General.TransactionOutOfMemoryError`; Python `DataError` | `capacity exceeded: used=… limit=…` | A growing write crossed `--logical-graph-size-limit`. | Raise the limit or reduce the graph. | no | 1 |
| `engine-expression-memory-cap`; code `fatal_error`, kind `capacity` | `This statement tried to build a single value of <size>. This is a safety limit protecting against memory exhaustion (not a database limit) — build the value in smaller pieces, or raise it with --expression-memory-limit.` | One statement built a single value (a list, a string, a map) larger than the per-value expression cap, 256 MiB by default. | Build the value in smaller pieces, or raise `--expression-memory-limit` (`none` disables the cap for a known bulk pipeline). | no | 1 |
| `engine-system-ontologies-not-queryable`; code `validation_error`, kind `semantic`; GQL status `42N17`; Python `OperationalError` | `This database is not queryable. Use the db.ontology.* procedures on the user database 'neo4j' instead.` | A statement other than an administration command was routed to `system_ontologies`, reads included. | Run `CALL db.ontology.get()` on `neo4j` with `RELATE_PREVIEW=ontology` set. | — | 6 |
| `engine-system-ontologies-write`; GQL status `42N18`; HTTP 400 | — | A write against the read-only `system_ontologies` namespace. | Write on `neo4j`; the ontology is set through `db.ontology.*`. | — | — |
| `engine-unsupported-administration-command`; code `validation_error`, kind `semantic`; GQL status `51N27`; HTTP 400; Python `NotSupportedError` | `Unsupported administration command: <statement>` | A database administration command beyond `SHOW DATABASE[S]`, `SHOW DEFAULT/HOME DATABASE` and `ALTER DATABASE … SET DEFAULT LANGUAGE CYPHER 5\|25`. | A store has three fixed namespaces; there is nothing to create, drop or alias. | no | 6 |
| `engine-use-on-administration-command`; code `validation_error`, kind `syntax`; GQL status `42N79` | ``UseClauseWithAdministrationCommand: The `USE` clause is not required for administration commands. Retry your query without the `USE` clause, and it will be routed automatically.`` | An explicit `USE` targeting a non-system namespace on an administration command. | Drop the `USE` clause. | no | 6 |
| `engine-with-on-system`; code `validation_error`, kind `semantic` | `The following clauses are not allowed on a system database: WITH.` | A `WITH` composing an administration command routed to `system`. | Run the administration command without composing it. | no | 6 |
| `engine-composite-only-function`; code `validation_error`, kind `semantic`; GQL status `42N72` | `semantic error: SemanticError: Dynamic graph lookup not allowed here. This feature is only available on composite databases. Attempted to access graph <name>` | `graph.byName`, `graph.names` or `graph.propertiesByName`, which are composite-only. | A statement runs against one graph; query each store separately. | no | 6 |
| `engine-multiple-use-targets`; code `validation_error`, kind `semantic`; GQL status `42NA5` | `semantic error: SemanticError: Multiple graphs in the same query not allowed here. This feature is only available on composite databases. Attempted to access graph <name>` | Several distinct `USE` targets in one statement (across `UNION` arms, `CALL` subqueries or `NEXT`). | Use one target per statement. | no | 6 |
| `engine-unknown-function`; code `validation_error`, kind `syntax`; GQL status `42N48` | `UnknownFunction: unknown function <name>()` | The function name is unknown, or it is a preview function whose gate is off. | Check the name with `SHOW FUNCTIONS`; preview functions need `RELATE_PREVIEW`. | no | 6 |
| `engine-procedure-not-found`; code `validation_error`, kind `syntax` | `syntax error: ProcedureNotFound: <name>` | `CALL` names a procedure relate does not have. | Check the name with `SHOW PROCEDURES`; APOC and GDS are not included ([differences from Neo4j](https://relatedb.ai/docs/reference/cypher/differences-from-neo4j/)). | no | 6 |
| `engine-preview-feature-not-enabled`; code `validation_error`, kind `semantic` | `preview feature '<name>' is not enabled: set RELATE_PREVIEW=<name>` | A gated preview feature was used while disabled. For ontology the full text is `semantic error: SemanticError: preview feature 'ontology' is not enabled: set RELATE_PREVIEW=ontology`. Not every preview feature fails with this message: obfuscated-literals fails as `syntax error: parse error: unexpected token "*"`, mixed-label-syntax as `InvalidLabelExpression` or `MixedIsAndColonConjunction`, complex-search-patterns as `SearchClauseTooComplexPattern` or `SearchClauseMultipleBoundVariables`, and the coll-zip, coll-has and gql-stddev-aliases name gates as `UnknownFunction` ([Cypher overview](https://relatedb.ai/docs/reference/cypher/overview/), the When off column). | Set `RELATE_PREVIEW=<name>` in the environment of the process that opens the store. | — | 6 |
| `engine-safe-mode-violation`; code `validation_error`, kind `syntax`; name `SafeModeViolation`; GQL status `42N06`; Neo4j `Neo.ClientError.Statement.SyntaxError`; HTTP 400 | ``syntax error: SafeModeViolation: This statement is not allowed in safe mode: an unbounded read (`MATCH … RETURN` or `MATCH … WITH` without `LIMIT`). Safe mode refuses shapes an agent commonly gets wrong — add `LIMIT <n>`, or return an aggregate such as `count(*)`, so the read has a bounded result. This is a policy, not a database limit; reopen without --safe to allow it.`` | Safe mode (`--safe`) refused a new named node without a label, or a `MATCH` read whose final `RETURN`/`WITH` has no `LIMIT` and no reducing aggregate (`collect()` does not count). The message above is the unbounded-read refusal. An unlabeled new node gets `syntax error: SafeModeViolation: This statement is not allowed in safe mode: CREATE or MERGE of a new node `n` without a label. …`. | Add the label, or add a `LIMIT`. | no | 6 |
| `engine-traversal-depth-exceeded`; code `validation_error`, kind `syntax`; name `TraversalDepthExceeded`; GQL status `42N06`; Neo4j `Neo.ClientError.Statement.SyntaxError`; HTTP 400 | `syntax error: TraversalDepthExceeded: This query allows paths up to <n> hops. This is a safety limit protecting against excessive traversal (not a database limit) — lower the path bound, or raise it with --max-traversal-depth (up to 2000).` | An explicit `*1..N` or `{1,N}` bound is above `--max-traversal-depth` (default 500). | Lower the bound, or raise `--max-traversal-depth` (at most 2000). | no | 6 |
| `engine-query-too-large`; code `validation_error`, kind `syntax` | `syntax error: query text of <n> bytes exceeds the maximum query size of 4194304 bytes` | The statement text is over 4 MiB (4,194,304 bytes). | Send the data as parameters, or split the statement. | no | 6 |
| `engine-nesting-depth-exceeded`; code `validation_error`, kind `syntax` | `syntax error: parse error: maximum nesting depth of 500 exceeded` | The statement's expressions and clauses nest more than 500 levels deep. The error object also carries `column` and `source`. | Flatten the expression. | no | 6 |
| `engine-value-depth-exceeded`; code `fatal_error`, kind `execution`; name `ValueDepthExceeded` | `ValueDepthExceeded: value nesting exceeds 500 levels; container nesting compounds per level (security limit).` | A list or map built at run time nests more than 500 levels. | Build a flatter value. | no | 1 |
| `engine-nested-evaluation-budget`; code `fatal_error`, kind `execution`; Neo4j `Neo.ClientError.Statement.SemanticError` | `NestedEvaluationBudgetExceeded: nested evaluation exceeds 100000 passes per statement; nested subqueries compound per level (security budget).` | Nested subqueries, conditional branches and `FOREACH` lists would exceed 100,000 evaluation passes in one statement. A `CALL` subquery runs once per input row and each run counts against the budget, so a `CALL { … }` over more than 100,000 rows fails, `IN TRANSACTIONS` included; the same statement over 99,999 rows succeeds. | Flatten the nesting or split the statement. | no | 1 |
| `engine-write-on-read-only`; code `validation_error`, kind `semantic`; name `WriteOnReadOnlyAccessDatabase`; GQL status `42N18`; Neo4j `Neo.ClientError.Statement.SemanticError`; Python `OperationalError` | `semantic error: WriteOnReadOnlyAccessDatabase: No write operations are allowed on this database. The database is in read-only mode on this Neo4j instance.` | A write on a store opened `--read-only` (or an ephemeral `--load` into `:memory:`). A `--load` into `:memory:` is read-only too. The Bolt server's message is `database is read-only`. The C ABI clients (Java `ClientException`, Go `*relate.Error`, Swift `.engine`) report this code and GQL status, stage runtime, on a write or a checkpoint. On the HTTP Query API a write in a managed transaction on a store served `--read-only` runs inside the transaction and the commit answers 400 with `42N18`. | Reopen without `--read-only` when the write is intended. | no | 6 |
| `engine-uniqueness-violation`; code `validation_error`, kind `semantic`; Neo4j `Neo.ClientError.Schema.ConstraintValidationFailed`; Python `IntegrityError` | ``semantic error: ConstraintValidationFailed: `<constraint>` uniqueness`` | A write violates a uniqueness constraint. | Use `MERGE` on the constrained key, or fix the duplicate. | no | 6 |
| `engine-vector-dimension-mismatch`; code `validation_error`, kind `type` | `type error: vector() dimension does not match list` | `vector(list, n, type)` was given a list whose length is not `n`. | Pass a dimension equal to the list length. | no | 6 |
| `engine-vector-index-dimensionality-mismatch`; code `validation_error`, kind `type` | `type error: VectorIndexDimensionalityMismatch` | A query vector or a stored vector whose length is not the index's `vector.dimensions`. | Embed with the model the index was built for, or create the index with the right dimension. | no | 6 |
| `engine-equivalent-schema-rule-already-exists`; code `validation_error`, kind `semantic` | `semantic error: EquivalentSchemaRuleAlreadyExists` | An index equivalent to an existing one: a vector index on the same label and property with the same `WITH [...]` list (same properties, same order), whatever its `OPTIONS`, or a full-text index on the same label and properties. | Check `SHOW INDEXES`; the existing index already serves the statement, or give the new vector index a different `WITH` list. | no | 6 |
| `engine-index-already-exists`; code `validation_error`, kind `semantic` | `semantic error: IndexAlreadyExists` | A `CREATE INDEX` names an index that already exists. | Add `IF NOT EXISTS`. | no | 6 |
| `engine-no-such-index`; code `validation_error`, kind `semantic` | `` semantic error: NoSuchIndex: `<name>` `` | A `DROP INDEX` names an index that does not exist. | Check `SHOW INDEXES`, or add `IF EXISTS`. | no | 6 |
| `engine-namespace-change-in-transaction`; Python `OperationalError` | `Cannot change the namespace while a transaction is open.` | `Connection.set_namespace` with a transaction open. Through the C ABI (Java, Go, Swift) the message is `semantic error: TransactionError: Cannot change the namespace while a transaction is open.`, code `Neo.ClientError.Statement.SemanticError`, GQL status `42000`. | Commit or roll back first. | — | — |
| `engine-already-in-transaction`; GQL status `42000`; Neo4j `Neo.ClientError.Statement.SemanticError` | `semantic error: already in a transaction` | A second begin while a transaction is open; transactions do not nest. In the CLI shell a second `.begin` prints the message and exits 1; the Node.js client raises it from `begin()`. | Commit or roll back the open transaction first. | no | 1 |
| `engine-transaction-failed-rollback-required`; GQL status `42000`; Neo4j `Neo.ClientError.Statement.SemanticError`; HTTP 400 | `semantic error: transaction failed; rollback required` | A statement failed inside an explicit transaction; every later statement and the commit fail until rollback. The CLI stops a script at its first failure, so it does not reach this error. On the HTTP Query API, a failed statement in a managed transaction (22G03, 42N06, 42N02 and others) poisons it: every later statement and the commit answer 400 with this message and GQL status `42000`; an empty keep-alive still answers 200; a commit that gets it closes the transaction with nothing written; a refusal under `accessMode` READ does not poison it. | Roll back, then run the transaction again. | no | — |
| `engine-constraint-requires-properties`; code `validation_error`, kind `semantic`; Python `IntegrityError` | ``semantic error: ConstraintValidationFailed: `<constraint>` requires properties`` | A write leaves a property that an `IS NOT NULL` constraint requires unset. | Set the property in the same write. | no | 6 |
| `engine-constraint-property-type`; code `validation_error`, kind `semantic`; Python `IntegrityError` | ``semantic error: ConstraintValidationFailed: `<constraint>` property type`` | A write stores a value of another type than an `IS :: <TYPE>` constraint requires. | Store a value of the required type. | no | 6 |
| `engine-constraint-already-exists`; code `validation_error`, kind `semantic` | `semantic error: ConstraintAlreadyExists` | `CREATE CONSTRAINT` with a name that is taken, without `IF NOT EXISTS`. | Add `IF NOT EXISTS`, or choose another name. | no | 6 |
| `engine-constraint-not-found`; code `validation_error`, kind `semantic` | `semantic error: ConstraintNotFound` | `DROP CONSTRAINT` names no constraint, without `IF EXISTS`. | Check the name with `SHOW CONSTRAINTS`, or add `IF EXISTS`. | no | 6 |
| `engine-index-belongs-to-constraint`; code `fatal_error`, kind `execution` | `Unable to drop '<name>': the index belongs to a constraint.` | `DROP INDEX` on the index a uniqueness or key constraint owns. | Drop the constraint instead; its index goes with it. | no | 1 |
| `engine-constraint-index-already-exists`; code `validation_error`, kind `semantic` | `semantic error: AlreadyExists: there already exists an index (<schema>). A constraint cannot be created until the index has been dropped.` | A uniqueness constraint over a label and property that a range index already covers. | Drop the index, then create the constraint; the constraint brings its own index. | no | 6 |
| `engine-invalid-index-option`; code `validation_error`, kind `syntax` | `syntax error: InvalidIndexOption` | `CREATE INDEX … OPTIONS {…}` with a key other than `indexConfig`. | Put settings under `indexConfig`. | no | 6 |
| `engine-delete-connected-node`; code `fatal_error`, kind `execution`; Python `IntegrityError` | `DeleteConnectedNode: Cannot delete node with relationships unless DETACH` | `DELETE` on a node that still has relationships. | Use `DETACH DELETE`, or delete the relationships first. | no | 1 |
| `engine-merge-null-property`; code `fatal_error`, kind `execution` | `MergeReadOwnWrites: cannot MERGE with null properties` | A `MERGE` pattern with a property whose value is null. | Filter out the null first, or `MERGE` on the properties that have values. | no | 1 |
| `engine-invalid-property-type`; code `validation_error`, kind `type` | `type error: InvalidPropertyType` | A property value that cannot be stored: a map, a list of mixed types, or a list holding null. | Store a scalar or a homogeneous list without nulls; model a map as properties or nodes. | no | 6 |
| `engine-write-before-call-in-transactions`; code `validation_error`, kind `syntax` | `syntax error: WriteBeforeCallInTransactions: a write cannot precede CALL IN TRANSACTIONS` | A write, `LOAD CSV` included, before `CALL { … } IN TRANSACTIONS` in the same statement. | Move the write inside the subquery, or run it as its own statement. | no | 6 |
| `engine-system-restricted-clauses`; code `validation_error`, kind `semantic` | `semantic error: SemanticError: The following unsupported clauses were used: <clauses>.  The system database supports a restricted set of Cypher clauses. The supported clause structure for procedure calls is: CALL, YIELD, RETURN. YIELD and RETURN clauses are optional. The order of the clauses is fixed and each can only occur once.` | A `MATCH`, `RETURN` or other clause outside a procedure call, routed to the `system` namespace. Two spaces follow the first period, as printed. | Run the statement on `neo4j`, or use `SHOW …` or `CALL … YIELD … RETURN` on `system`. | no | 6 |
| `engine-point-latitude-range`; code `validation_error`, kind `argument` | `InvalidArgumentValue: point() latitude must be in the range [-90, 90]` | A geographic `point()` with a latitude outside -90 to 90; longitude and latitude may be swapped. The CLI prints it after `semantic error:`; the WebAssembly build after `type error:`. | Pass the latitude as `latitude` (or `y`) and keep it within range. | no | 6 |
| `engine-no-transaction`; GQL status `42000`; Neo4j `Neo.ClientError.Statement.SemanticError` | `semantic error: no transaction` | A commit or rollback with no explicit transaction open: `.commit` or `.rollback` in the shell, or `commit()`/`rollback()` in a client. The Java, Go, Swift and Node.js clients report it with GQL status `42000` and stage runtime; in a CLI script it stops the run with exit code 1. | Begin a transaction first, or drop the commit. | no | 1 |
| `engine-ontology-unsupported-version`; code `validation_error`, kind `semantic` | `semantic error: Unsupported ontology spec version: '<uri>'. This version of Relate supports up to Ontology Graph Spec 1.1.0 ('https://neo4j.com/docs/ontology-graph-spec/1.1.0/schema.json').` | `db.ontology.set` got a document whose `schema` names a spec version this build does not support (preview: `RELATE_PREVIEW=ontology`). | Write the document against Ontology Graph Spec 1.1.0 or earlier. | no | 6 |
| `engine-ontology-argument-type`; code `validation_error`, kind `type` | ``type error: InvalidArgumentType: db.ontology.set argument `ontology` expects STRING`` | `db.ontology.set` got a map or another non-string value; the document is passed as one string (preview: `RELATE_PREVIEW=ontology`). | Pass the document as a string. | no | 6 |
| `engine-ontology-user-database-only`; code `validation_error`, kind `semantic` | `semantic error: SemanticError: Ontologies can only be stored for the user database 'neo4j'.` | An ontology procedure called with the session on the `system` namespace (preview: `RELATE_PREVIEW=ontology`). | Call it on `neo4j`. | no | 6 |

## HTTP Query API errors

Errors from `relate serve --http`, in the Query API v2 error envelope.

| Error | Message | Cause | Remedy | Retryable | Exit code |
| --- | --- | --- | --- | --- | --- |
| `http-unauthorized`; GQL status `42NFF`; HTTP 401 | — | Missing or wrong credential. | Send `Authorization: Basic` with the `serve` credential (the generated token is printed at startup). | — | — |
| `http-not-found`; GQL status `42N00`; HTTP 404 | — | Unknown `{databaseName}`, or any unknown route. An unknown path answers the message `not found`; an unknown namespace `semantic error: DatabaseNotFound: Graph not found: <name>`. | Use `neo4j` or `system`. | — | — |
| `http-transaction-expired`; GQL status `42N90`; HTTP 404 | `transaction <id> expired after <n>s idle` | A managed transaction sat idle past `--tx-idle-timeout-secs`. Message pattern from the recorded example `transaction tx-7 expired after 60s idle`. | Begin a new transaction; raise the idle timeout if needed. | — | — |
| `http-transaction-registry-full`; GQL status `42N91`; HTTP 429 | `transaction registry full: 128 open transactions (close one or raise --max-open-transactions)` | A begin over the `--max-open-transactions` cap. The count in the message is the configured cap. | Close an open transaction or raise the cap. | — | — |
| `http-malformed-or-syntax`; GQL status `42N06`; HTTP 400 | — | Malformed request body, or a Cypher syntax error. | Fix the body or the statement. | — | — |
| `http-general`; GQL status `42000`; HTTP 400 | — | Any other caller-facing engine error, undecodable `parameters`, or (with 405) a wrong method; with 500, an IO, storage or locked failure, genericized. Observed messages: a body over the 16 MiB cap is `malformed request: body too large`; a request line that is not HTTP/1.1 is `unsupported HTTP version HTTP/1.0: this surface answers HTTP/1.1`; a wrong method (405) is `method not allowed`. | Read the message. | — | — |
| `http-internal`; GQL status `50N42`; HTTP 500 | — | Engine-internal error; the message is genericized. | Report it with the server version. | — | — |
| `http-unsupported-media-type`; GQL status `42000`; HTTP 415 | `the request content type is browser-"simple" — a cross-origin form cannot send a non-simple type without a preflight` | A `POST` with no `Content-Type`, or a browser-simple one (`text/plain` or a form type; `curl -d` sends `application/x-www-form-urlencoded`). | Send `Content-Type: application/json`. | — | — |
| `http-origin-forbidden`; GQL status `42000`; HTTP 403 | `origin is not allowed` | A browser request whose `Origin` is not the server's own and not one `--origin` allows. | Add the page's origin with `--origin`. | — | — |
| `http-read-transaction-write`; GQL status `42000`; HTTP 400 | `writing is not allowed in a READ transaction` | A write in a managed transaction begun with `"accessMode": "READ"`. It does not poison the transaction. | Begin the transaction without `accessMode`, or with `WRITE`. | — | — |
| `http-transaction-not-found`; GQL status `42000`; HTTP 404 | `transaction <id> not found` | The transaction id was never issued, or the transaction was committed, rolled back or closed after a failed commit. | Begin a new transaction. | — | — |

## Bolt errors

Errors from `relate serve --bolt` that the Bolt surface adds to the engine errors.

| Error | Message | Cause | Remedy | Retryable | Exit code |
| --- | --- | --- | --- | --- | --- |
| `bolt-unauthorized`; Neo4j `Neo.ClientError.Security.Unauthorized` | `The client is unauthorized due to authentication failure.` | A failed or missing auth token; the connection closes. A Bolt 4.4 HELLO with a wrong or missing credential answers the message `authentication failed`; the message in this row is the Bolt 5.4 LOGON failure. | Use the `serve` credential. | — | — |
| `bolt-request-invalid`; Neo4j `Neo.ClientError.Request.Invalid` | — | A malformed message: a RUN without a string statement, a bad PULL/DISCARD `n` or `qid`, an unconvertible parameter, a HELLO without `user_agent`, or a protocol breach. | Use a supported Neo4j driver. | — | — |
| `bolt-result-too-large`; Neo4j `Neo.ClientError.General.TransactionOutOfMemoryError` | `query result exceeds max-result-bytes limit of <N> bytes` | A result over the Bolt server's fixed cap of 256 MiB of retained data per connection; `relate serve` has no flag that changes it. | Add `LIMIT` or page the result. | — | — |

## MCP errors

Errors from `relate serve --mcp`. A tool refusal comes back as a tool result with `isError: true`; a protocol error is a JSON-RPC error with the code in its row.

| Error | Message | Cause | Remedy | Retryable | Exit code |
| --- | --- | --- | --- | --- | --- |
| `mcp-read-query-only` | `Only MATCH queries are allowed for read-query` | `read_cypher` received a write (`w`/`rw`) or schema DDL (`s`) statement. Any pure read passes, `OPTIONAL MATCH` included. | Use `write_cypher` for writes, where the server lists it. | — | — |
| `mcp-write-query-only` | `Only write queries are allowed for write-query` | `write_cypher` received a read-only statement. `write_cypher` is absent when the store is opened `--read-only`. | Use `read_cypher`. | — | — |
| `mcp-unknown-tool` | `unknown tool '<name>'` | `tools/call` named a tool the server does not list; `write_cypher` is not listed when the store is opened `--read-only`. Returned as a tool result with `isError: true`, not as a JSON-RPC error. | Call a tool from `tools/list`; to write, serve the store without `--read-only`. | — | — |
| `mcp-internal-error` | `Error: internal error` | An internal-class engine failure (engine-internal, IO, storage, locked); detail is genericized so it never reaches tool-call logs. | Check the server's own stderr. | — | — |
| `mcp-method-not-found`; JSON-RPC -32601 | `Method not found: <method>` | Unknown JSON-RPC method. | Use `initialize`, `ping`, `tools/list` or `tools/call`. | — | — |
| `mcp-invalid-params`; JSON-RPC -32602 | `Invalid params: <detail>` | Malformed `tools/call` params. | Match the tool's input schema. | — | — |
| `mcp-parse-error`; JSON-RPC -32700 | `malformed JSON-RPC message: <detail>` | A body that is not JSON, omits `jsonrpc` or `method`, or carries an unknown member. | Send a strict JSON-RPC 2.0 message. | — | — |
| `mcp-unsupported-version`; JSON-RPC -32600 | `unsupported JSON-RPC version '<version>'` | A `jsonrpc` version other than `2.0`. | Send `"jsonrpc": "2.0"`. | — | — |
| `mcp-missing-statement` | `invalid params: missing string "statement"` | A Cypher tool call without a `statement` string. A tool result with `isError: true`. | Pass the statement as `statement`. | — | — |
| `mcp-parameters-not-object` | `invalid params: "parameters" must be an object` | `parameters` is a string, list, number or boolean; `null` is accepted as no parameters. A tool result with `isError: true`. | Pass `parameters` as an object, or leave it out. | — | — |
| `mcp-bad-sample-size` | `invalid params: sample_size must be -1 or non-negative, got <n>` | `get_schema` with a negative `sample_size` other than -1. A tool result with `isError: true`. | Pass -1 (every node) or a count of zero or more. | — | — |
| `mcp-http-unauthorized`; HTTP 401 | `{"error":"authentication required"}` | The MCP HTTP transport got no credential, or the wrong one; the response carries `WWW-Authenticate: Basic realm="relate"`. | Send `Authorization: Basic` with the `serve` credential. | — | — |
| `mcp-http-unsupported-media-type`; HTTP 415 | `{"error":"the request content type is browser-\"simple\" — a cross-origin form cannot send a non-simple type without a preflight"}` | A `POST` to the MCP HTTP transport with no `Content-Type`, or `text/plain` or a form type. | Send `Content-Type: application/json`. | — | — |
| `mcp-http-origin-forbidden`; HTTP 403 | `{"error":"origin is not allowed"}` | A browser request to the MCP HTTP transport from an origin `--origin` does not allow. | Send the request without an `Origin` header or from a loopback origin; the MCP transport has no `--origin` setting. | — | — |
| `mcp-http-method-not-allowed`; HTTP 405 | `{"error":"streamable HTTP MCP is POST-only"}` | A `GET` or another method on the MCP HTTP endpoint; the response carries `Allow: POST`. | Send JSON-RPC requests with `POST`. | — | — |

## Client library errors

Refusals a client library raises itself, before or around the engine: the Node.js client's argument checks, the WebAssembly build's storage and loading errors, and the C ABI's own messages. The `Error` column names the surface and, where the client has one, the class.

| Error | Message | Cause | Remedy | Retryable | Exit code |
| --- | --- | --- | --- | --- | --- |
| `node-params-not-object`; name `TypeError` | `query params must be a plain object` | The second argument of `query` is not a plain object (an array, a class instance, a string). | Pass parameters as a plain object, `{ name: value }`. | no | — |
| `node-extra-arguments`; name `TypeError` | `query takes (cypher, params?) — extra arguments` | `query` got more than a statement and a parameters object. | Put every parameter in the one object. | no | — |
| `node-not-a-statement`; name `TypeError` | `query expects a Cypher string or a tagged template` | `query` got neither a string nor a tagged template. | Pass the statement as a string, or call it as a tagged template. | no | — |
| `node-param-not-cypher`; name `TypeError` | `query params: <path> cannot be a Cypher parameter` | A parameter value has no Cypher type: a function, a symbol, `undefined` inside a list, and similar. `<path>` is the parameter name in double quotes, plus `[<i>]` or `.<key>` for a nested value. | Convert the value to a number, string, boolean, list, plain object or one of the client's value classes. | no | — |
| `node-param-map-not-object`; name `TypeError` | `query params: <path> must be a plain object` | A nested map value is not a plain object. `<path>` is the parameter name in double quotes, plus `[<i>]` or `.<key>` for a nested value. | Pass nested maps as plain objects. | no | — |
| `node-param-int64-range`; name `TypeError` | `query params: <path> is an integer outside the int64 range` | A `BigInt` parameter outside the 64-bit signed range. `<path>` is the parameter name in double quotes, plus `[<i>]` or `.<key>` for a nested value. | Keep integers within -2^63 to 2^63 - 1. | no | — |
| `node-param-cyclic`; name `TypeError` | `query params: <path> is cyclic` | A parameter list or object refers to itself. `<path>` is the parameter name in double quotes, plus `[<i>]` or `.<key>` for a nested value. | Pass a value without cycles. | no | — |
| `node-vector-coordinate-integer`; name `TypeError` | `query params: <path> coordinate <i> must be an integer for dtype <dtype>` | A vector parameter with an integer `dtype` holds a coordinate that is not an integer. `<path>` is the parameter name in double quotes, plus `[<i>]` or `.<key>` for a nested value. | Use whole numbers, or a float `dtype`. | no | — |
| `node-vector-coordinate-number`; name `TypeError` | `query params: <path> coordinate <i> must be a number for dtype <dtype>` | A vector parameter with a float `dtype` holds a coordinate that is not a number. `<path>` is the parameter name in double quotes, plus `[<i>]` or `.<key>` for a nested value. | Use numbers for every coordinate. | no | — |
| `node-sync-while-async`; name `RelateError` | `a synchronous <call> cannot start while an async query is in flight on this connection` | A synchronous call on a connection while one of its async queries has not settled. `code`, `gqlStatus` and `stage` are null. | Await the async query first, or use another connection. | no | — |
| `node-ffi-not-found`; name `Error` | `librelate_ffi not found; looked in (1) the RELATE_LIB environment variable, (2) the platform package @relate/<platform>-<arch> (lib/ directory), (3) the repo target/debug and target/release directories. Set RELATE_LIB to the library path.` | The native library is not installed for this platform: the optional platform package was skipped, or the platform has none. | Install the package again with optional dependencies, or set `RELATE_LIB` to the library path. | no | — |
| `wasm-opfs-needs-worker` | `storage error: OPFS needs a dedicated worker` | `RelateDb.open()` ran on the page's thread, or in a shared or service worker. | Run the engine in a dedicated worker. | no | — |
| `wasm-opfs-name` | `OPFS name must be 1-64 characters from [A-Za-z0-9_-]` | The name after `opfs://` is empty, too long, or has another character (`opfs://team.rl`, `opfs://a/b`). | Use letters, digits, `_` and `-` only. | no | — |
| `wasm-opfs-uri` | `OPFS open requires an opfs://name URI; use new RelateDb() for :memory:` | `RelateDb.open()` got a path, a `file://` URL or `:memory:`; the browser build opens only OPFS and in-memory stores. | Pass `opfs://<name>`, or use `new RelateDb()` for an in-memory store. | no | — |
| `wasm-opfs-locked` | `storage locked: opfs://<name>` | Another handle holds the store, from any worker of the same origin, in this tab or another. `prepareOpfs` throws the same message with `name` `RelateLocked`. | Send statements to the worker that holds it, or free that handle first. | no | — |
| `wasm-opfs-unavailable` | `storage error: OPFS is not available in this browser` | The worker has no `navigator.storage.getDirectory`. | Use an in-memory store in this browser. | no | — |
| `wasm-read-only-reset` | `database is read-only` | `reset()` on a handle opened read-only. | Open the store writable to reset it. | no | — |
| `wasm-use-after-free` | `null pointer passed to rust` | A call on a handle after `free()`. | Open a new handle. | no | — |
| `wasm-invalid-params-json` | `invalid params JSON: <detail>` | The parameters string passed to `query` does not parse as JSON. It comes back as an error envelope, not a throw. | Pass `JSON.stringify` of an object. | no | — |
| `wasm-params-not-object` | `params must be a JSON object` | The parameters string parses, but not to an object. It comes back as an error envelope. | Pass a JSON object. | no | — |
| `wasm-fetch-failed` | `failed to fetch Wasm: <status> <statusText> fetching '<url>'` | `init` fetched `relate_bg.wasm` and got a non-2xx status, such as `404 Not Found` when the file is not beside `relate.js`. | Serve `relate_bg.wasm` beside `relate.js`, or pass its URL to `init`. | no | — |
| `wasm-envelope-no-columns` | ``envelope <i>: no `columns` array`` | `renderResult` got an entry, counted from 0, that is JSON without a `columns` array, such as `{}`. | Pass the text `query` returned. | no | — |
| `c-null-out-pointer` | `null out pointer` | A C ABI call got a NULL output pointer where it writes a result, such as `relate_conn_commit` with a NULL `bookmark_out`. | Pass a pointer to a variable for the call to fill. | no | — |
| `c-ffi-internal-error` | `ffi internal error: <message>` | The stderr line `RELATE_FFI_LOG` prints for an internal failure behind a C ABI call. | Report it with the message; the call returned an error object. | no | — |

## GQL status index

Each GQL status code, at its own anchor (`#gql-42n00`), with the entries that report it.

| GQL status | Errors |
| --- | --- |
| `22G03` | [cli-validation-error-type](https://relatedb.ai/docs/reference/errors/#cli-validation-error-type); [engine-division-by-zero](https://relatedb.ai/docs/reference/errors/#engine-division-by-zero) |
| `42000` | [http-general](https://relatedb.ai/docs/reference/errors/#http-general); [engine-storage-locked](https://relatedb.ai/docs/reference/errors/#engine-storage-locked); [engine-already-in-transaction](https://relatedb.ai/docs/reference/errors/#engine-already-in-transaction); [engine-transaction-failed-rollback-required](https://relatedb.ai/docs/reference/errors/#engine-transaction-failed-rollback-required); [engine-no-transaction](https://relatedb.ai/docs/reference/errors/#engine-no-transaction); [http-unsupported-media-type](https://relatedb.ai/docs/reference/errors/#http-unsupported-media-type); [http-origin-forbidden](https://relatedb.ai/docs/reference/errors/#http-origin-forbidden); [http-read-transaction-write](https://relatedb.ai/docs/reference/errors/#http-read-transaction-write); [http-transaction-not-found](https://relatedb.ai/docs/reference/errors/#http-transaction-not-found) |
| `42N00` | [engine-database-not-found](https://relatedb.ai/docs/reference/errors/#engine-database-not-found); [http-not-found](https://relatedb.ai/docs/reference/errors/#http-not-found) |
| `42N02` | [engine-parameter-missing](https://relatedb.ai/docs/reference/errors/#engine-parameter-missing) |
| `42N06` | [engine-safe-mode-violation](https://relatedb.ai/docs/reference/errors/#engine-safe-mode-violation); [engine-traversal-depth-exceeded](https://relatedb.ai/docs/reference/errors/#engine-traversal-depth-exceeded); [http-malformed-or-syntax](https://relatedb.ai/docs/reference/errors/#http-malformed-or-syntax) |
| `42N17` | [engine-system-ontologies-not-queryable](https://relatedb.ai/docs/reference/errors/#engine-system-ontologies-not-queryable) |
| `42N18` | [engine-system-ontologies-write](https://relatedb.ai/docs/reference/errors/#engine-system-ontologies-write); [engine-write-on-read-only](https://relatedb.ai/docs/reference/errors/#engine-write-on-read-only) |
| `42N48` | [engine-unknown-function](https://relatedb.ai/docs/reference/errors/#engine-unknown-function) |
| `42N72` | [engine-composite-only-function](https://relatedb.ai/docs/reference/errors/#engine-composite-only-function) |
| `42N79` | [engine-use-on-administration-command](https://relatedb.ai/docs/reference/errors/#engine-use-on-administration-command) |
| `42N90` | [http-transaction-expired](https://relatedb.ai/docs/reference/errors/#http-transaction-expired) |
| `42N91` | [http-transaction-registry-full](https://relatedb.ai/docs/reference/errors/#http-transaction-registry-full) |
| `42NA5` | [engine-multiple-use-targets](https://relatedb.ai/docs/reference/errors/#engine-multiple-use-targets) |
| `42NFF` | [http-unauthorized](https://relatedb.ai/docs/reference/errors/#http-unauthorized) |
| `50N42` | [cli-fatal-error-internal](https://relatedb.ai/docs/reference/errors/#cli-fatal-error-internal); [http-internal](https://relatedb.ai/docs/reference/errors/#http-internal) |
| `51N27` | [engine-unsupported-administration-command](https://relatedb.ai/docs/reference/errors/#engine-unsupported-administration-command) |

## Python exception classes

The classes the Python client (`relate-db`) raises, at their own anchors.

| Class | Parent | Raised for |
| --- | --- | --- |
| `Error`; alias `RelateError` | `Exception` | Base of every relate database error. |
| `InterfaceError` | `Error` | Native module communication. |
| `DatabaseError` | `Error` | Fallback for an unmapped engine error. |
| `DataError` | `DatabaseError` | Bad type or value; every capacity refusal (kind MemoryLimitExceeded); an out-of-range int parameter. |
| `OperationalError` | `DatabaseError` | Open, I/O, transaction; namespace errors; writes on a read-only database. |
| `IntegrityError` | `DatabaseError` | Constraint violations and deleting a still-connected node without DETACH. |
| `InternalError` | `DatabaseError` | An engine invariant the caller cannot fix. |
| `ProgrammingError` | `DatabaseError` | Syntax errors, missing parameters, parameter-shape mistakes, closed connections, wrong-thread use. |
| `NotSupportedError` | `DatabaseError` | Unsupported administration commands. |
| `ResultNotSingleError` | `ProgrammingError` | `cursor.single()` got zero rows or more than one. |

Every exception carries the attributes `kind`, `tck_class`, `neo4j_code`, `gql_status`, `stage`, `retryable`.

## Notifications

Notifications are not errors: a statement that raises one still runs. `EXPLAIN` and `PROFILE` print them after the plan, and `--mode envelope` carries them in `notifications`.

| Notification | GQL status | Code | Severity | Category | Title |
| --- | --- | --- | --- | --- | --- |
| `notif-00na0` | `00NA0` | `Neo.ClientNotification.Schema.IndexOrConstraintAlreadyExists` | INFORMATION | SCHEMA | Index or constraint already exists |
| `notif-00na1` | `00NA1` | `Neo.ClientNotification.Schema.IndexOrConstraintDoesNotExist` | INFORMATION | SCHEMA | Index or constraint does not exist |
| `notif-00na2` | `00NA2` | `Neo.ClientNotification.Schema.VectorIndexDimensionsNotSpecified` | INFORMATION | SCHEMA | Vector index dimensions not specified |
| `notif-01n00`; name `CallSubqueryWithoutScope / MergeSelfReference / CreateSelfReference` | `01N00` | `Neo.ClientNotification.Statement.FeatureDeprecationWarning` | WARNING | DEPRECATION | — |
| `notif-01n01`; name `DeprecatedFunction / DeprecatedProcedure / AmbiguousSubclauseReference / ComplexSubclauseReference` | `01N01` | `Neo.ClientNotification.Statement.FeatureDeprecationWarning` | WARNING | DEPRECATION | — |
| `notif-01n30` | `01N30` | `Neo.ClientNotification.Statement.JoinHintUnfulfillableWarning` | WARNING | HINT | The database was unable to plan a hinted join. relate 0.16.1 was not observed to emit it. |
| `notif-01n31` | `01N31` | `Neo.ClientNotification.Schema.HintedIndexNotFound` | WARNING | HINT | The request (directly or indirectly) referred to an index that does not exist. relate 0.16.1 was not observed to emit it. |
| `notif-01n50` | `01N50` | `Neo.ClientNotification.Statement.UnknownLabelWarning` | WARNING | UNRECOGNIZED | Unknown label |
| `notif-01n51` | `01N51` | `Neo.ClientNotification.Statement.UnknownRelationshipTypeWarning` | WARNING | UNRECOGNIZED | Unknown relationship type |
| `notif-01n52` | `01N52` | `Neo.ClientNotification.Statement.UnknownPropertyKeyWarning` | WARNING | UNRECOGNIZED | Unknown property key |
| `notif-01n61` | `01N61` | `Neo.ClientNotification.Statement.UnsatisfiableRelationshipTypeExpression` | WARNING | UNRECOGNIZED | Unsatisfiable relationship type expression |
| `notif-01n63` | `01N63` | `Neo.ClientNotification.Statement.RepeatedRelationshipVariable` | WARNING | UNRECOGNIZED | Repeated relationship pattern variable |
| `notif-03c90` | `03C90` | `Relate.Notification.Statement.AllNodesScan` | INFORMATION | PERFORMANCE | All nodes scan |
| `notif-03c91` | `03C91` | `Relate.Notification.Statement.MissingIndex` | INFORMATION | PERFORMANCE | Missing index |
| `notif-03c92` | `03C92` | `Relate.Notification.Statement.EagerAggregation` | INFORMATION | PERFORMANCE | Eager aggregation |
| `notif-03c93`; name `EstimationMiss` | `03C93` | `Relate.Notification.Statement.EstimationMiss` | INFORMATION | PERFORMANCE | Estimation miss; PROFILE only. |
| `notif-03n60` | `03N60` | `Neo.ClientNotification.Statement.SubqueryVariableShadowing` | INFORMATION | UNRECOGNIZED | Subquery variable shadowing |
| `notif-03n63` | `03N63` | `Neo.ClientNotification.Statement.IdentifierShadowingVariable` | INFORMATION | UNRECOGNIZED | Identifier shadowing variable |
| `notif-03n90` | `03N90` | `Neo.ClientNotification.Statement.CartesianProduct` | INFORMATION | PERFORMANCE | Cartesian product |
| `notif-03n91` | `03N91` | `Neo.ClientNotification.Statement.UnboundedVariableLengthPattern` | INFORMATION | PERFORMANCE | Unbounded variable-length pattern |
| `notif-03n92` | `03N92` | `Neo.ClientNotification.Statement.ExhaustiveShortestPath` | INFORMATION | PERFORMANCE | Exhaustive shortest path |
| `notif-03n95` | `03N95` | `Neo.ClientNotification.Statement.DynamicProperty` | INFORMATION | PERFORMANCE | Queries using dynamic properties will use neither index seeks nor index scans for those properties |

## See also

- [Connect your agent to relate](https://relatedb.ai/docs/get-started/agent-quickstart/): reading an error object and branching on its exit code
- [Exit codes and errors](https://relatedb.ai/docs/reference/cli/exit-codes-and-errors/): the exit code table and every field of the error object
- [Troubleshooting](https://relatedb.ai/docs/guides/operate/troubleshooting/): from an error message or exit code to the guide that fixes it

## Terms used on this page

- **exit code**: The number a `relate` run returns to the shell; each nonzero value names a class of failure, such as 2 for usage, 5 for conflict, 6 for a rejected statement.
- **error object**: The JSON object a failed query run prints on stdout in the `json`, `jsonl`, `envelope` and `speedscope` modes: the class, the kind, the message, the exit code.
- **surface**: Any front door to the relate engine: the CLI, a language client, the C ABI, the WebAssembly build, or a server that `relate serve` hosts.
