API Reference

Auto-generated from docstrings. Every exported symbol is listed below.

Connection

SurrealDB.connectFunction
connect(url::String; ns=nothing, db=nothing, token=nothing, auth=nothing)
connect(f::Function, url::String; kwargs...)

Connect to a SurrealDB instance. The URL scheme determines the backend:

URL schemeBackendDescription
ws://host:portRemote WSWebSocket (stateful)
http://host:portRemote HTTPHTTP (stateless)
mem://EmbeddedIn-memory database
surrealkv://pathEmbeddedFile-backed database

Keyword arguments:

  • ns, db: Namespace and database to select after connecting
  • token: JWT token for authentication
  • auth: Auth struct (RootAuth, NamespaceAuth, etc.) for signin
  • reconnect::Bool=true: Auto-reconnect on socket drop (WS only)
  • reconnect_max_attempts::Int=10: Consecutive failures before giving up
  • reconnect_base_delay::Float64=0.5: Initial backoff (exponential, in seconds)
  • reconnect_max_delay::Float64=30.0: Cap on the backoff delay
  • reconnect_jitter::Float64=0.1: Random jitter factor [0,1] applied to each backoff
  • ping_interval::Float64=30.0: Keepalive cadence; 0 disables
  • tls_verify::Bool=true: Verify TLS certs on wss://. Set false only for self-signed test certs
  • rpc_timeout::Float64=30.0: Max seconds to wait for an RPC response; Inf disables

Returns a SurrealClient{C} where C is the concrete connection backend type.

Do-block form

The function form mirrors Base.open: the client is closed automatically on exit, even if the block throws.

SurrealDB.connect("ws://localhost:8000"; ns="test", db="test") do db
    SurrealDB.query(db, "SELECT * FROM stream")
end  # client is closed here
source
SurrealDB.close!Function
close!(client::SurrealClient)

Close the database connection. The client cannot be used after this call.

source
SurrealDB.statusFunction
status(client::SurrealClient)

Return the current connection status as a Symbol: :connected, :disconnected, :connecting, :reconnecting

source
SurrealDB.eventsFunction
events(client::SurrealClient{<:AbstractRemoteConnection}) -> Channel{Symbol}

Return a Channel that emits lifecycle event symbols on remote-connection state transitions: :connecting, :connected, :reconnecting, :disconnected. Drop-in equivalent of the JS SDK's db.subscribe('connected', ...) pattern. Best-effort emission — if no consumer drains the channel, events are queued (capacity 64) and dropped silently when the buffer is full.

Only RemoteConnection emits events today; embedded connections have a much simpler lifecycle (connect succeeds or throws) so the Channel exists but is never written to.

Examples

db = SurrealDB.connect("ws://localhost:8000")
@async for ev in SurrealDB.events(db)
    @info "SurrealDB lifecycle" event=ev status=SurrealDB.status(db)
end
source
SurrealDB.SurrealClientType
SurrealClient{C<:AbstractConnection}

The main client type for interacting with a SurrealDB database.

Generic over the connection backend type C. Create via connect.

Examples

db = SurrealDB.connect("ws://localhost:8000")
SurrealDB.use!(db, "test", "test")
result = SurrealDB.query(db, "SELECT * FROM stream")
source
SurrealDB.RemoteConnectionType
RemoteConnection(url)

A remote connection to a SurrealDB server via WebSocket or HTTP.

URL schemes accepted:

  • ws://host:port / wss://host:port — WebSocket (primary, stateful)
  • http://host:port / https://host:port — HTTP (stateless)
source
SurrealDB.RemoteWSConnectionType
RemoteConnection(url)

A remote connection to a SurrealDB server via WebSocket or HTTP.

URL schemes accepted:

  • ws://host:port / wss://host:port — WebSocket (primary, stateful)
  • http://host:port / https://host:port — HTTP (stateless)
source
SurrealDB.RemoteHTTPConnectionType
RemoteConnection(url)

A remote connection to a SurrealDB server via WebSocket or HTTP.

URL schemes accepted:

  • ws://host:port / wss://host:port — WebSocket (primary, stateful)
  • http://host:port / https://host:port — HTTP (stateless)
source
SurrealDB.Embedded.EmbeddedConnectionType
EmbeddedConnection(url)

An embedded SurrealDB connection running in-process via libsurreal.

URL schemes:

  • mem:// or memory:// — in-memory database (no persistence)
  • surrealkv://path/to/data.skv — file-backed database

Requires libsurreal to be loaded via libsurreal_load!.

source

Authentication

SurrealDB.signin!Function
signin!(client, auth) -> token::String

Authenticate with the SurrealDB server.

auth can be:

  • RootAuth - root-level credentials
  • NamespaceAuth - namespace-level credentials
  • ScopedAuth - record-level credentials via an access method
  • Dict{String, Any} - raw parameters (e.g., for bearer keys, refresh tokens)

Returns the JWT token string on success. The SDK stores the token on the client so subsequent RPCs are authenticated automatically; the token is also replayed on reconnect.

Examples

token = SurrealDB.signin!(db, SurrealDB.RootAuth("root", "password"))

token = SurrealDB.signin!(db, SurrealDB.NamespaceAuth("ns", "db", "user", "pass"))

token = SurrealDB.signin!(db, SurrealDB.ScopedAuth("ns", "db", "access", "user", "pass"))

token = SurrealDB.signin!(db, Dict("NS" => "ns", "DB" => "db", "AC" => "access",
                                    "user" => "u", "pass" => "p"))
source
SurrealDB.signup!Function
signup!(client, auth::ScopedAuth)

Register a new user via a RECORD-scope access method.

Returns the JWT token string on success.

Note: SurrealDB signup is only available with RECORD-scoped access methods.

source
SurrealDB.authenticate!Function
authenticate!(client, token::String)

Authenticate the current connection with a pre-obtained JWT token.

This is useful when you have a JWT from a previous signin or an external auth system.

Examples

SurrealDB.authenticate!(db, "eyJ0eXAiOiJKV1QiLCJh...")
source
SurrealDB.invalidate!Function
invalidate!(client)

Clear the current authentication session. Subsequent operations will be unauthenticated.

source
SurrealDB.ScopedAuthType
ScopedAuth(namespace, database, access, username, password)
ScopedAuth(namespace, database, access, params::AbstractDict)

Scoped authentication credentials (record-level auth via an access method).

The 5-arg form is the convenience case for SIGNIN clauses that reference $user / $pass. The dict form passes through arbitrary keys for SIGNIN clauses referencing other params ($email, $name, etc.).

SurrealDB.signin!(db, SurrealDB.ScopedAuth("ns", "db", "user_access", "alice", "hunter2"))
SurrealDB.signin!(db, SurrealDB.ScopedAuth("ns", "db", "user_access",
                                            Dict("email" => "a@example.com",
                                                 "pass"  => "hunter2")))
source

Database scope

SurrealDB.use!Function
use!(client::SurrealClient, ns::String, db::String)

Select a namespace and database for all subsequent operations.

source
SurrealDB.infoFunction
info(client::SurrealClient)

Retrieve database-level information such as tables and schema.

Returns a Dict{String, Any}.

source
SurrealDB.versionFunction
version(client::SurrealClient)

Retrieve the SurrealDB server version.

Returns a NamedTuple with fields :version, :build, :timestamp.

source
SurrealDB.healthFunction
health(client::SurrealClient)

Check the health of the database connection.

Returns true if the database is healthy.

source

Query and CRUD

SurrealDB.queryFunction
query(client, sql::String; vars=Dict{String, Any}())

Execute a raw SurrealQL query with optional parameterized variables.

Returns Vector{Dict{String, Any}} — one result dict per statement.

Examples

result = SurrealDB.query(db, "SELECT * FROM stream WHERE active = true")
result = SurrealDB.query(db, "SELECT * FROM $table WHERE x > $min",
                         vars=Dict("table" => "stream", "min" => 10))
source
query(client, ::Type{T}, sql::String; vars=Dict{String, Any}())

Execute a raw SurrealQL query and map results to typed Julia structs.

T must be a type for which StructTypes.StructType(T) returns StructTypes.Struct(). Each result row is converted to an instance of T via StructTypes.constructfrom.

Returns Vector{T} — one instance per result row.

Examples

struct Stream
    id::SurrealDB.RecordID
    name::String
    mature::Bool
end
StructTypes.StructType(::Type{Stream}) = StructTypes.Struct()

streams = SurrealDB.query(db, Stream, "SELECT * FROM stream")
source
SurrealDB.query_tableFunction
query_table(client, sql::String; vars=Dict{String, Any}()) -> Vector{QueryResultTable}

Like query but returns one QueryResultTable per statement instead of nested vectors. Lets multi-statement queries preserve their per-statement structure as Tables.jl-compatible sources.

Embedded mode flattens statement boundaries

Remote (WS/HTTP) preserves per-statement results. Embedded (libsurreal) flattens all rows from all statements into a single result list (the C library does not expose statement boundaries). On embedded, query_table therefore returns a single-element Vector regardless of how many ;s the SQL contains. Run multi-statement queries one at a time on embedded if you need per-statement separation.

Examples

tables = SurrealDB.query_table(db, "SELECT * FROM stream; SELECT * FROM event")
using DataFrames
streams_df = DataFrame(tables[1])
events_df  = DataFrame(tables[2])

See also: query, query_one, to_table.

source
SurrealDB.query_oneFunction
query_one(client, sql::String; vars=Dict{String, Any}()) -> QueryResultTable

Convenience wrapper around query_table for single-statement queries. Asserts the SQL produced exactly one statement-result and returns its QueryResultTable. Throws ArgumentError if the query produced zero or multiple statements.

Examples

table = SurrealDB.query_one(db, "SELECT * FROM stream WHERE active = true")
using DataFrames
df = DataFrame(table)

See also: query, query_table.

source
SurrealDB.createFunction
create(client, what, data::Dict{String, Any})

Create a new record in the table or with a specific ID.

  • what: Table name (String or Table) or record ID (RecordID)
  • data: Record fields as a Dict

Returns the created record(s) as a Dict or Vector of Dicts.

source
create(client, ::Type{T}, what, data)

Create a record and return it as a typed struct T.

Examples

stream = SurrealDB.create(db, Stream, "stream", Dict("name" => "new"))
source
SurrealDB.selectFunction
select(client, what) -> Any

Select all records from a table or fetch a specific record by ID.

Returns a Vector of records when what is a table, or a single record (Dict) when what is a record ID. Returns an empty vector / nothing when the target does not exist.

See also: create, update, delete.

source
select(client, ::Type{T}, what)

Select a record or table and map results to typed Julia struct T.

For table selects, returns Vector{T}. For record selects, returns T.

Examples

struct Stream
    id::SurrealDB.RecordID
    name::String
end
StructTypes.StructType(::Type{Stream}) = StructTypes.Struct()

all_streams = SurrealDB.select(db, Stream, "stream")
one_stream = SurrealDB.select(db, Stream, "stream:abc")
source
SurrealDB.updateFunction
update(client, what, data) -> Any

Replace the contents of a record (or every record in a table) with data. Existing fields not present in data are removed; for partial updates use merge instead.

  • what: Table name or record ID
  • data: Replacement record contents (Dict)

Returns the updated record(s).

See also: merge, upsert, patch.

source
SurrealDB.deleteFunction
delete(client, what) -> Any

Delete a record or every record in a table.

  • what: Table name or record ID

Returns the deleted record(s). Deleting a nonexistent record is not an error on SurrealDB v3 (returns nothing).

See also: select, create.

source
SurrealDB.insertFunction
insert(client, table, data) -> Any

Insert one or many records into a table. Unlike create, data may be a single Dict or a Vector of Dicts for batch inserts; ids are auto-assigned when not provided.

  • table: Table name (String or Table)
  • data: Single Dict or Vector of Dicts

Returns the inserted record(s).

See also: create, insert_relation.

source
SurrealDB.upsertFunction
upsert(client, what, data) -> Any

Create the record if it does not exist, otherwise replace it. Same payload shape as update; the difference is that update on a missing record may not create it on all SurrealDB versions.

See also: update, merge.

source
SurrealDB.mergeFunction
merge(client, what, data) -> Any

Partially update a record by merging data into the existing record. Fields present in data overwrite existing fields; fields absent are preserved (unlike update which replaces the whole record).

  • what: Table name or record ID
  • data: Partial record contents (Dict)

See also: update, patch.

source
SurrealDB.relateFunction
relate(client, from, edge, to; data=nothing) -> Any
relate(client, rel::Relationship) -> Any

Create a graph edge from from to to via edge. The flat-arg form is the canonical first-class signature; the Relationship form is convenient for storing/passing pre-built edges.

  • from: source record id (RecordID or "table:id" string)
  • edge: edge table (Table or String) or specific edge record id
  • to: target record id
  • data: optional Dict of edge fields

Returns the created edge record.

Examples

SurrealDB.relate(db, "person:john", "knows", "person:jane";
                 data=Dict("met" => "2024-01-01"))

# Or via the bulk struct
rel = Relationship("person:john", Table("knows"), "person:jane",
                   Dict("met" => "2024-01-01"))
SurrealDB.relate(db, rel)

See also: insert_relation, Relationship.

source
SurrealDB.insert_relationFunction
insert_relation(client, relationship::Relationship) -> Any

Insert a graph edge defined by a Relationship. Equivalent to SurrealQL INSERT RELATION INTO <table> { in, out, ... }.

Differs from relate in that insert_relation is intended for batch / seeded edges; relate is the canonical first-class edge primitive.

See also: relate, Relationship.

source
SurrealDB.patchFunction
patch(client, what, patches::Vector{Dict{String, Any}})

Apply JSON Patch operations to a record.

Examples

SurrealDB.patch(db, "user:1", [
    Dict("op" => "replace", "path" => "/name", "value" => "New Name"),
    Dict("op" => "add", "path" => "/tags/0", "value" => "new-tag")
])
source
SurrealDB.patch_removeFunction
patch_remove(client, what, path::String)

Convenience wrapper around patch that issues a single JSON-Patch remove operation at path.

source
SurrealDB.patch_replaceFunction
patch_replace(client, what, path::String, value)

Convenience wrapper around patch that issues a single JSON-Patch replace operation at path.

source
SurrealDB.runFunction
run(client, fn_name::String, args=Any[]; version=nothing) -> Any

Invoke a SurrealDB function — builtin (type::*, string::*, ...) or user-defined (fn::*).

  • fn_name: Function name including namespace, e.g. "fn::greet" or "type::is::array"
  • args: Positional args as a Vector
  • version: Optional semver string for versioned user functions

Examples

SurrealDB.run(db, "type::is::array", [[1, 2, 3]])  # → true
SurrealDB.run(db, "fn::greet", ["world"])
source
SurrealDB.pingFunction
ping(client::SurrealClient) -> Bool

Send a lightweight RPC ping. Returns true if the server responds. Backs the keepalive timer; exposed for callers who want a manual liveness check without health()'s trivial-query fallback.

source
SurrealDB.let!Function
let!(client, key::String, value)

Set a session variable. These variables can be referenced in SurrealQL queries using $key syntax.

Examples

SurrealDB.let!(db, "min_age", 18)
result = SurrealDB.query(db, "SELECT * FROM user WHERE age > $min_age")
source

Live queries

SurrealDB.liveFunction
live(client, table; diff=false)

Start a live query subscription on a table.

Returns a LiveSubscription with a channel field you can iterate over to receive real-time notifications.

  • table: Table name (String or Table)
  • diff: If true, notifications include the diff between old and new values

Examples

sub = SurrealDB.live(db, "stream")
for notification in sub.channel
    println("Action: ", notification["action"])
    println("Data: ", notification["data"])
    break  # or loop forever
end
SurrealDB.kill!(sub)
source
SurrealDB.kill!Function
kill!(client, query_id::String)

Terminate a live query by its UUID. If a LiveSubscription handle was registered for this id (i.e. created via live), its active flag is flipped to false and its channel is closed so consumers iterating it observe the termination.

source
kill!(sub::LiveSubscription)

Terminate a live query subscription. Delegates to kill! by id, which flips sub.active and closes the channel.

source
SurrealDB.LiveSubscriptionType
LiveSubscription(query_id, channel, client)

A live query subscription. Iterate over sub.channel (or sub directly) to receive LiveNotification events. Call kill!(sub) to terminate.

Fields:

  • query_id::String: UUID string identifying the live query on the server
  • channel::Channel: receives LiveNotification events
  • active::Bool: subscription state
source
SurrealDB.LiveNotificationType
LiveNotification(action, query_id, record, result, session)

One live-query event delivered to a LiveSubscription channel. Subtype of AbstractDict{String, Any} so legacy n["action"] access keeps working alongside the typed n.action form.

Fields:

  • action::String: "CREATE", "UPDATE", or "DELETE" ("KILLED" events are dropped by the dispatcher)
  • query_id::String: live UUID matching sub.query_id
  • record::Union{String, Nothing}: affected record id, e.g. "users:abc"
  • result::Any: payload — the record on CREATE/UPDATE, the pre-delete record on DELETE
  • session::Union{String, Nothing}: v3 session id; nothing on v2
source

Transactions and sessions

SurrealDB.begin!Function
begin!(client)

Start a new transaction. All subsequent operations within the transaction are isolated until commit! or cancel! is called.

On SurrealDB v3+ remote connections, begin!/commit!/cancel! RPC methods may return "Expected transaction UUID". Use raw SurrealQL instead:

SurrealDB.query(db, "BEGIN TRANSACTION; ...; COMMIT TRANSACTION;")
source
begin!(session::SurrealSession)

Start a transaction within a v3+ session.

Returns the transaction UUID. Pass this to commit! or cancel!.

source
SurrealDB.commit!Function
commit!(client)

Commit the active transaction, persisting all changes made within it. For v3+ remote connections, prefer raw SurrealQL COMMIT TRANSACTION;.

source
commit!(session::SurrealSession, txn_id)

Commit a transaction within a v3+ session.

source
SurrealDB.cancel!Function
cancel!(client)

Cancel / rollback the active transaction, discarding all changes made within it. For v3+ remote connections, prefer raw SurrealQL CANCEL TRANSACTION;.

source
cancel!(session::SurrealSession, txn_id)

Cancel/rollback a transaction within a v3+ session.

source
SurrealDB.attach!Function
attach!(client)

Create a new ephemeral session on the server (SurrealDB v3+).

Returns a UUID session identifier. The session is independent — it has its own namespace, database, auth, and variables. Use detach! to clean up.

WebSocket-only (not supported on HTTP connections).

source
SurrealDB.detach!Function
detach!(client, session_id::UUID)

Destroy a server-side session (SurrealDB v3+).

After detaching, the session cannot be used for further operations.

source
SurrealDB.sessionsFunction
sessions(client)

List active session UUIDs on the server (SurrealDB v3+).

Returns Vector{UUID}.

source
SurrealDB.SurrealSessionType
SurrealSession

A v3+ server-side session wrapping a SurrealClient.

Fields:

  • client::SurrealClient — the underlying connection
  • session_id::UUID — the server-assigned session identifier

All operations on this session are scoped to the session's namespace, database, auth, and variables.

source

Import / Export

SurrealDB.export_dbFunction
export_db(client::SurrealClient, filepath::String)

Export the current namespace and database to a file.

source
SurrealDB.import_dbFunction
import_db(client::SurrealClient, filepath::String)

Import data from a file into the current namespace and database.

source

Embedded mode

SurrealDB.Embedded.libsurreal_load!Function
libsurreal_load!(path::String="")

Load the libsurreal shared library at path for embedded mode. When path is empty, falls back to the SURREALDB_LIB environment variable.

Must be called before connect("mem://") or connect("surrealkv://..."). Remote connections (ws://, http://) don't need this.

Examples

SurrealDB.libsurreal_load!("/path/to/libsurrealdb_c.dylib")
db = SurrealDB.connect("mem://")
source

Tables.jl and graph extensions

SurrealDB.to_tableFunction
to_table(results) -> QueryResultTable

Convert query results to a Tables.jl-compatible source. Can be passed directly to DataFrame() from DataFrames.jl, Tables.columntable, etc.

results can be:

  • A Vector{Dict{String, Any}} (single-statement result rows)
  • A Vector{Any} containing nested vectors of dicts (multi-statement; rows are flattened across all statements)
  • A single Dict (treated as a one-row table)
source
SurrealDB.to_metagraphFunction
to_metagraph(vertices, edges; ...)
to_metagraph(client::SurrealClient, vertices_query::String, edges_query::String; ...)

Materialize query results into a MetaGraphsNext.MetaGraph (with vertex labels = record-id strings, vertex/edge data = field Dicts). Method bodies live in the SurrealDBMetaGraphsNextExt Pkg extension, loaded automatically by Julia 1.9+ when the user has MetaGraphsNext and Graphs in their environment.

If the extension isn't loaded, calls throw a clear error pointing the user at the right install command.

source
SurrealDB.QueryResultTableType
QueryResultTable

A Tables.jl-compatible wrapper around query results. Stores rows as a Vector{Dict{String, Any}} and delegates Tables.jl operations to Tables.dictrowtable / Tables.dictcolumntable so columns are derived lazily on access (no eager materialization). Use to_table to construct from raw query results.

Examples

result = SurrealDB.query(db, "SELECT * FROM stream")
table = SurrealDB.to_table(result)
using DataFrames
df = DataFrame(table)        # column-major access
for row in Tables.rows(table)  # row-major iteration
    println(row)
end
source

Core types

SurrealDB.RecordIDType
RecordID(table, id)

Represents a SurrealDB record identifier consisting of a table name and an ID.

Examples

RecordID("user", "abc123")           # table + string id
RecordID("user", 42)                 # table + integer id
RecordID("user:abc123")              # parse from string
source
SurrealDB.TableType
Table(name)

Represents a SurrealDB table name. Wraps a String for clarity in the API.

Examples

Table("stream")
source
SurrealDB.SurrealValueType
SurrealValue(kind::SurrealValueKind, value)

A tagged union representing any SurrealDB value type. Used internally for precision type handling when mapping to/from C FFI types in embedded mode.

Most users never construct one directly — query / select / etc. handle the conversions automatically.

source
SurrealDB.RelationshipType
Relationship(in, relation, out; data=Dict())

Represents a graph relationship between two records.

Examples

rel = Relationship("person:john", Table("knows"), "person:jane",
                    data=Dict("met" => "2024-01-01"))
source

Errors

SurrealDB.ServerErrorType
ServerError <: SurrealDBError

Abstract supertype for errors that originated server-side (i.e. the SurrealDB engine reported the failure). Mirrors the kind-tagged ServerError hierarchy in surrealdb.js and surrealdb.py — concrete subtypes correspond to the kind field of the wire-protocol error payload.

Concrete subtypes:

Catch ServerError to handle any server-side failure uniformly; catch a specific subtype for kind-aware handling.

source
SurrealDB.RPCErrorType
RPCError(code, message)

Represents a JSON-RPC error returned by the SurrealDB server. This includes transport errors, protocol errors, and server-side failures.

Fields:

  • code::Int: JSON-RPC numeric error code
  • message::String: Human-readable error message from the server
source
SurrealDB.QueryErrorType
QueryError(message)

A SurrealQL parse or execution failure. Subtype of ServerError.

Fields:

  • message::String: Error message describing the query failure
  • is_timed_out::Bool: true when the server reports the query timed out
  • is_cancelled::Bool: true when the query was cancelled mid-execution

Bare-message constructor is supported for backward compat: QueryError(msg)QueryError(msg, false, false).

source
SurrealDB.NotFoundErrorType
NotFoundError(message; table_name=nothing, record_id=nothing, namespace_name=nothing)

A referenced record, table, or namespace does not exist. Subtype of ServerError.

source
SurrealDB.ConnectionErrorType
ConnectionError(message, cause)

Represents a connection-level failure (WebSocket disconnect, timeout, etc.).

Fields:

  • message::String: Description of the connection failure
  • cause::Union{Exception, Nothing}: Underlying exception that caused the failure, if any
source
SurrealDB.ConnectionUnavailableErrorType
ConnectionUnavailableError(message="No active connection to the database.")

The client is not connected (or has been closed). Distinct from ConnectionError which represents transport-level failures during an attempt; this is raised for "no connection at all" scenarios.

source
SurrealDB.UnsupportedFeatureErrorType
UnsupportedFeatureError(feature, transport=nothing)

The requested operation is not supported on the current transport (e.g. live queries over HTTP). feature is a Symbol naming the feature; transport optionally names the transport that lacks support.

source
SurrealDB.UnexpectedResponseErrorType
UnexpectedResponseError(message)

The server returned a response in an unexpected shape. Used when the wire format doesn't match any of the documented response variants.

source
SurrealDB.EmbeddedFFIErrorType
EmbeddedFFIError(op, message)

A failure originating from the embedded libsurreal FFI layer. Distinct from RPCError (which represents server-side JSON-RPC failures) and ConnectionError (transport-level failures) so callers can distinguish "libsurreal misbehaved" from "the network blinked."

Fields:

  • op::String: the FFI operation that failed (e.g. "sr_patch_add", "_self_test_layout")
  • message::String: error message — either propagated from the C library or describing the layout/lookup mismatch
source