Errors
A call can fail because a definition is missing, a document is invalid, or the database refuses a change. The examples use the people data to show these results. Use the status and diagnostic fields to identify the failure.
Binding errors
| Language | Failure |
|---|---|
| C | Returns a status. The owner that its operation names holds the diagnostic. |
| Go | Returns *Error. |
| Rust | Returns Result<_, Error>. |
| Clojure | Throws clojure.lang.ExceptionInfo with diagnostic data. |
| Python | Raises StardustError. |
| Odin | Returns an Error beside its result. |
The error record gives the fields in your language. Statuses gives the failure conditions of each operation.
error
This record describes a failure with its status and diagnostic. The binding copies the diagnostic before it releases the native owner.
| Field | Type | Unit | Absent |
|---|---|---|---|
code | String | None | — |
message | String | None | — |
path | Option<String> | None | None |
field | Option<String> | None | None |
entity | Option<i64> | None | None |
offset | Option<i64> | Bytes | None |
status | Status | None | — |
Statuses
Each status names a class of failure. The table lists codes from the binding. Native diagnostic codes can differ.
Status::INVALID_ARGUMENT
Codes: time_out_of_range, invalid_argument, out_of_range, non_finite_number, cycle, unsupported_type, too_large, native_failure, live_children, wrong_kind, not_integral, inexact_number, missing_field, unknown_field, duplicate_field, too_deep, length_mismatch, malformed_tag, ambiguous_field, ambiguous_variant, invalid_value, hook_failed.
| When | Operations |
|---|---|
the entity ID is outside the user entity range, max_depth is negative or above 32, or max_entities is negative | Database::read_entity |
the text is malformed, the format is unknown or a number is outside i64 or finite f64 | parse |
| the format is unknown or the width is negative | Document::serialize |
| the text is malformed, a format is unknown or the width is negative | convert |
the value has a host type with no document form (one the language's standard JSON encoder also refuses), a number outside i64 or finite f64, a decimal or time with no exact native form, a failing conversion method, or a cycle | from_value |
| the node breaks the preorder rules or has an invalid kind or number | Builder::add |
| a node breaks the preorder rules or has an invalid kind or number | Builder::add_many |
| the builder has no root or a container is still open | Builder::seal |
| id is not a node of the document | Document::read, Document::children |
| start is past the last node or capacity is negative | Document::read_many |
| id is not an object node of the document | Document::member, Document::members |
| the node is not an integer number | Document::i64 |
the node is not a number or its value overflows f64 | Document::f64 |
| the arguments include an undeclared macro parameter | build_macro, expand_macro |
| the file is not a database, an option is invalid or selected plugins are incompatible | open |
| the parameters or run options are invalid | Query::run, Mutation::run |
| the parameters or subscription options are invalid | Query::subscribe |
| the patch is not an entity-keyed object, or a link names an ID outside the user entity range | Database::merge_patch |
| the kind, action, revision or page limits are invalid, or the selected plan cannot run the current authored definition | Database::plan |
| the kind or the pattern is invalid | Database::definitions |
| a bulk build is already in progress on the database | Database::bulk_begin |
| no bulk build is in progress | Database::bulk_add, Database::bulk_finish |
| a name is empty, the plugin has no call operation with the name, or the plugin refuses the request | Database::plugin_call |
| a name is empty, the plugin has no stream operation with the name, or the plugin refuses the request | Database::plugin_stream |
| the stream has finished or does not accept writes | PluginStream::write |
| the stream does not support reads, or length is negative | PluginStream::read |
the stream does not support seeks, whence is unknown, or the position is negative or past the i64 range | PluginStream::seek |
| the stream has finished or has no finish step | PluginStream::finish |
| the token is empty or longer than 4096 bytes | activate |
| entity is not a user entity | Objects::get, Objects::path |
| the parent or the name is invalid, or the parent is a file | Objects::lookup |
| the parent is invalid or is a file | Objects::children |
| the digest is not 64 hexadecimal digits | Objects::files, Objects::manifest, Objects::open |
| the array is empty or malformed, a name is invalid, or a parent is a file | Objects::create |
the entity is a directory or invalid, the digest is malformed, or expected_revision is negative | Objects::update |
| the request is malformed, the destination is a file or inside the node, the kinds differ, or a replaced directory is not empty | Objects::move |
the entity is invalid, the directory is not empty, or expected_revision is negative | Objects::remove |
| options is not an object, or an option is invalid, duplicated or unsupported | Reactors::sync, Backups::sync, Sdk::sync |
Status::INVALID_JSON
Status::COMPILE_FAILED
| When | Operations |
|---|---|
| the expression does not compile | build |
| the expansion does not compile | build_macro |
| the expanded expression does not compile | Database::expression |
Status::EVALUATION_FAILED
| When | Operations |
|---|---|
| the expression fails on the input | Program::evaluate |
the query fails or exceeds max_cost | Query::run |
| the page does not render | Rows::next_page |
| a page does not render | Rows::pages, Rows::all_pages |
| a rerun of the query failed. Every later call reports this failure | Subscription::next |
| a rerun of the query failed | Subscription::events |
| the mutation fails | Mutation::run |
| the plugin cannot read its stored state | Database::plugin_call, Database::plugin_stream |
| stored bytes do not match their digest | PluginStream::read |
| stored tree metadata or the manifest of a named payload is corrupted | Objects::get, Objects::lookup, Objects::children, Objects::path |
| the stored manifest is corrupted | Objects::manifest, Objects::open |
Status::OUT_OF_MEMORY
Codes: out_of_memory.
Status::NOT_FOUND
Codes: not_found.
| When | Operations |
|---|---|
| the object has no member with the key | Document::member |
| the macro refers to an unknown macro | build_macro, expand_macro |
| the parent directory is missing, or the file is missing and create is false | open |
| no definition is stored at the path | Database::query, Database::mutation, Database::definition |
| no expression is stored at the path | Database::expression |
| the stored query definition was deleted | Query::run |
| the definition or exact historical plan revision does not exist | Database::plan |
| the plugin reports that the request names nothing it holds | Database::plugin_call, Database::plugin_stream |
| no object node has the entity | Objects::get |
| the parent has no child with the name, or the parent does not exist | Objects::lookup |
| the parent does not exist | Objects::children |
| the node or one of its ancestors does not exist | Objects::path |
| no payload with the digest is published | Objects::manifest, Objects::open |
| a parent does not exist or a digest is not published | Objects::create |
| the file does not exist or the digest is not published | Objects::update |
| the node or the destination does not exist | Objects::move |
| the node does not exist | Objects::remove |
Status::LOCKED
| When | Operations |
|---|---|
another process holds the lock after lock_timeout | open |
| the shared wake dispatcher has no signal admission slot | Query::subscribe |
Status::CONFLICT
| When | Operations |
|---|---|
an enabled plugin finds the database inconsistent with its copies: backups refuse diverging copies with code backup_history_divergent, naming them | open |
| concurrent writes prevent the commit | Mutation::run |
| an entity revision check fails or a concurrent writer prevents the commit; a revision mismatch reports the entity and expected and actual revisions | Database::merge_patch |
| the authored definition or accepted plan changed before the explicit control committed | Database::plan |
| another write committed to the database during the build | Database::bulk_finish |
| the plugin's write lost to a concurrent change, or the database holds writes | Database::plugin_call |
| the database holds writes | Database::plugin_stream, PluginStream::finish, Objects::upload |
| the database holds writes while the plugin stores the bytes | PluginStream::write |
| a name is already taken in its parent or appears twice, or the database holds writes | Objects::create |
expected_revision is stale, or the database holds writes | Objects::update, Objects::remove |
the name is occupied without replace, expected_revision is stale, or the database holds writes | Objects::move |
Status::INVALID_DEFINITION
| When | Operations |
|---|---|
| the macro is invalid or expands recursively | build_macro, expand_macro |
| the definition is invalid | Database::query, Database::mutation |
| a macro it calls is invalid or expands recursively | Database::expression |
| the loaded query definition is invalid | Query::run |
| the query or its callable definitions are invalid | Query::subscribe |
| the mutation selection or definition is invalid | Mutation::run |
| the patched definition is invalid | Database::patch_definition |
Status::SCHEMA_VIOLATION
| When | Operations |
|---|---|
| the write breaks a schema | Mutation::run |
Status::INVALID_COMMIT_TIME
| When | Operations |
|---|---|
the #_tx commit time is not later than the last commit | Database::merge_patch |
Status::CLOSED
Codes: closed.
| When | Operations |
|---|---|
| the database is closed | Database::read_entity, Database::query, Database::mutation, Database::expression, Database::merge_patch, Database::definition, Database::plan, Database::definitions, Database::patch_definition, Database::indexes_sync, Database::bulk_begin, Database::bulk_add, Database::bulk_finish, Database::plugin_call, Database::plugin_stream, Objects::get, Objects::lookup, Objects::children, Objects::path, Objects::files, Objects::manifest, Objects::create, Objects::update, Objects::move, Objects::remove, Objects::upload, Objects::open, Reactors::status, Reactors::sync, Backups::status, Backups::sync, Sdk::status, Sdk::sync |
| the query is closed | Query::run, Query::subscribe |
| the rows is closed | Rows::next_page, Rows::pages, Rows::all_pages |
| the mutation is closed | Mutation::run |
the plugin_stream is closed | PluginStream::write, PluginStream::read, PluginStream::seek, PluginStream::finish |
Status::REJECTED
| When | Operations |
|---|---|
| a mutation target or write guard refuses the write | Mutation::run |
| the database refuses the patch; the code and diagnostic path name the reason and key | Database::merge_patch |
| the database refuses the patch; the build has failed and later adds report the same status | Database::bulk_add |
| the database refuses a patch; an initial build publishes nothing and fallback keeps earlier commits | Database::bulk_finish |
Status::UNSUPPORTED
Codes: abi_version, core_digest.
| When | Operations |
|---|---|
| found differs from the ABI version of the binding | check_version |
Status::CANCELLED
Codes: cancelled.
No core operation reports this status.
Status::TIMEOUT
| When | Operations |
|---|---|
max_wait passed first | Database::indexes_sync |
| the plugin's wait passed its limit | Database::plugin_call |
| maxWait passed before the work finished | Reactors::sync, Sdk::sync |
| maxWait passed before every target confirmed | Backups::sync |
Status::UNAVAILABLE
| When | Operations |
|---|---|
an enabled plugin cannot reach what the open needs: backups refuse with backup_targets_unreachable, backup_target_unreadable or backup_objects_required | open |
| the patch sets stardust/history and no enabled plugin purges history | Mutation::run, Database::merge_patch |
| the plugin is unknown or the database does not enable it | Database::plugin_call, Database::plugin_stream |
| the database does not enable the objects plugin | Objects::get, Objects::lookup, Objects::children, Objects::path, Objects::files, Objects::manifest, Objects::create, Objects::update, Objects::move, Objects::remove, Objects::upload, Objects::open |
| the database does not enable the reactors plugin | Reactors::status, Reactors::sync |
| the database does not enable the backups plugin | Backups::status, Backups::sync |
| the database does not enable the sdk plugin | Sdk::status, Sdk::sync |
Status::FAILED
| When | Operations |
|---|---|
| the plugin's work failed | Database::plugin_call |
| the plugin's work failed; status describes the failure | Reactors::sync, Backups::sync, Sdk::sync |
Status::UNLICENSED
Codes: unlicensed.
| When | Operations |
|---|---|
| the token is refused; the error names the reason | activate |
Refusal examples
The generator captured each result from the native library.
Describe the backup runtime
let result = db.backups().status().err();{:value {:code "unavailable"
:message "the plugin is not enabled"
:path nil
:field nil
:entity nil
:offset nil
:status "unavailable"}}Wait until every target stored the history
let sync_options = stardust::parse("{maxWait {#dur PT5S}}", Format::DUST)?;
let result = db.backups().sync(Some(&sync_options)).err();{:value {:code "unavailable"
:message "the plugin is not enabled"
:path nil
:field nil
:entity nil
:offset nil
:status "unavailable"}}convert
edn_text holds this document:
"{:a 1 :a 2}"let edn = stardust::parse(edn_text, Format::EDN)?;
let output = edn.read(edn.root()?)?.text;
let result = stardust::parse(output, Format::EDN).err();{:value {:code "invalid_edn"
:message "invalid EDN (Duplicate_Key) at offset 6"
:path nil
:field nil
:entity nil
:offset 6
:status "invalid_argument"}}Refuse a metadata-only transaction
patch_text holds this document:
{:#_tx {:author "x"}}let patch = stardust::parse(patch_text, Format::EDN)?;
let result = db.merge_patch(&patch, None).err();{:value {:code "transaction_only"
:message "a patch of only #_tx is refused: #_tx annotates a write"
:path "#_tx"
:field nil
:entity nil
:offset nil
:status "rejected"}}Refuse a repeated commit time
future_text holds this document:
{:#_d {:x 1}
:#_tx {:stardust/committedAt #inst "2200-01-01T00:00:00Z"}}older_text holds this document:
{:#_e {:x 2}
:#_tx {:stardust/committedAt #inst "2200-01-01T00:00:00Z"}}let future = stardust::parse(future_text, Format::EDN)?;
db.merge_patch(&future, None)?;
let older = stardust::parse(older_text, Format::EDN)?;
let result = db.merge_patch(&older, None).err();{:value {:code "invalid_commit_time"
:message "stardust/committedAt must be strictly newer than the latest commit time"
:path nil
:field nil
:entity nil
:offset nil
:status "invalid_commit_time"}}Refuse an invalid query definition
query_text holds this document:
{:find [?x]}let definition = stardust::parse(query_text, Format::EDN)?;
let result = db.query(&definition).err();{:value {:code "unbound_variable"
:message "Unbound_Variable"
:path nil
:field nil
:entity nil
:offset nil
:status "invalid_definition"}}Report a missing stored query
let result = db.query("people/missing").err();{:value {:code "not_found"
:message "no definition at this path"
:path "people/missing"
:field nil
:entity nil
:offset nil
:status "not_found"}}Report a malformed byte at offset zero
malformed holds these bytes:
]
let result = stardust::parse(malformed, Format::DUST).err();{:value {:code "invalid_dust"
:message "Invalid_Syntax at offset 0"
:path nil
:field nil
:entity nil
:offset 0
:status "invalid_argument"}}Report malformed DUST
malformed holds these bytes:
[
let result = stardust::parse(malformed, Format::DUST).err();{:value {:code "invalid_dust"
:message "Unexpected_End at offset 2"
:path nil
:field nil
:entity nil
:offset 2
:status "invalid_argument"}}