• Start

Concepts & Guides

Error handling

Handle errors in SurrealQL with THROW, validation guards and ASSERT on fields to stop queries and return clear failures.

Error handling in SurrealQL allows you to stop execution and return a meaningful error when something goes wrong. This is most commonly done using the THROW statement.

You can use THROW to immediately stop a query and return an error to the client:

THROW "Something went wrong";

When executed, the query is aborted and the error is returned.

THROW is often used to validate input or guard business logic:

IF !$email {
THROW "Email is required";
};

IF $amount <= 0 {
THROW "Transfer amount must be greater than zero";
};

THROW is especially useful inside manual transactions.

BEGIN TRANSACTION;

UPDATE account:one SET balance -= 150;

IF account:one.balance < 0 {
THROW "Insufficient funds";
};

COMMIT TRANSACTION;

The value passed to THROW is returned to the client.

THROW "Invalid username or password";

You can also include dynamic data:

THROW "User not found: " + <string>$username;

Or even structured data.

THROW {
code: 400,
message: "Invalid request"
};

Type safety and strict definitions can be used to avoid throwing errors based on custom logic. For example, the ASSERT clause in a DEFINE FIELD statement can be used to ensure that a statement will fail if the string for the email field provided is not a valid email.

DEFINE FIELD email ON TABLE user TYPE string
ASSERT string::is_email($value);

Working with a schema in this way allows throwing errors to be taken care of by the definitions themselves as opposed to writing custom logic.

SurrealDB uses a single public API error type that is shared by SDKs. As the repo states, the error type is:

Designed to be returned from public APIs (including over the wire). It is wire-friendly and non-lossy: serialization preserves kind, message, and optional details. Use this type whenever an error crosses an API boundary (e.g. server response, SDK method return).

The details field is flattened into the serialized object, so the wire format contains kind (string) and optionally details (object) at the same level as code and message. The optional cause field allows error chaining so that SDKs can receive and display full error chains.

This error will then be handled in a different manner depending on the programming language the SDK is written for.

Was this page helpful?