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 | str | None | — |
message | str | None | — |
path | str | None | None | None |
field | str | None | None | None |
entity | int | None | None | None |
offset | int | None | Bytes | None |
status | str | None | — |
Statuses
Each status names a class of failure. The table lists codes from the binding. Native diagnostic codes can differ.
"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 |
max_wait is negative | Subscription.next, Database.indexes_sync |
| 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 |
"invalid_json"
"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 |
"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 |
| 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 |
"out_of_memory"
Codes: out_of_memory.
"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 |
"locked"
| When | Operations |
|---|---|
another process holds the lock after lock_timeout | open |
"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 |
"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 |
"schema_violation"
| When | Operations |
|---|---|
| the write breaks a schema | Mutation.run |
"invalid_commit_time"
| When | Operations |
|---|---|
the #_tx commit time is not later than the last commit | Database.merge_patch |
"closed"
Codes: closed.
"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 |
"unsupported"
Codes: abi_version, core_digest.
| When | Operations |
|---|---|
| found differs from the ABI version of the binding | check_version |
"cancelled"
Codes: cancelled.
| When | Operations |
|---|---|
| the subscription is cancelled or closed | Subscription.next |
"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 |
"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 |
"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 |
"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
try:
await db.backups().status()
except stardust.StardustError as error:
result = error{
"code": "unavailable",
"message": "the plugin is not enabled",
"path": null,
"field": null,
"entity": null,
"offset": null,
"status": "unavailable"
}Wait until every target stored the history
async with await stardust.parse("{maxWait {#dur PT5S}}", "dust") as sync_options:
try:
await db.backups().sync(sync_options)
except stardust.StardustError as error:
result = error{
"code": "unavailable",
"message": "the plugin is not enabled",
"path": null,
"field": null,
"entity": null,
"offset": null,
"status": "unavailable"
}convert
edn_text holds this document:
"{:a 1 :a 2}"
async with (await stardust.parse(edn_text, "json")) as edn:
output = (await edn.read((await edn.root()))).text
try:
(await stardust.parse(output, "edn")).close()
except stardust.StardustError as error:
result = error{
"code": "invalid_edn",
"message": "invalid EDN (Duplicate_Key) at offset 6",
"path": null,
"field": null,
"entity": null,
"offset": 6,
"status": "invalid_argument"
}Refuse a metadata-only transaction
patch_text holds this document:
{
"#_tx": {
"author": "x"
}
}
async with (await stardust.parse(patch_text, "json")) as patch:
try:
(await db.merge_patch(patch))
except stardust.StardustError as error:
result = error{
"code": "transaction_only",
"message": "a patch of only #_tx is refused: #_tx annotates a write",
"path": "#_tx",
"field": null,
"entity": null,
"offset": null,
"status": "rejected"
}Refuse a repeated commit time
future_text holds this document:
{
"#_d": {
"x": 1
},
"#_tx": {
"stardust/committedAt": {
"#utc": "2200-01-01T00:00:00Z"
}
}
}
patch_text holds this document:
{
"#_e": {
"x": 2
},
"#_tx": {
"stardust/committedAt": {
"#utc": "2200-01-01T00:00:00Z"
}
}
}
async with (await stardust.parse(future_text, "json")) as future, (await stardust.parse(patch_text, "json")) as patch:
(await db.merge_patch(future))
try:
(await db.merge_patch(patch))
except stardust.StardustError as error:
result = error{
"code": "invalid_commit_time",
"message": "stardust/committedAt must be strictly newer than the latest commit time",
"path": null,
"field": null,
"entity": null,
"offset": null,
"status": "invalid_commit_time"
}Refuse an invalid query definition
query_text holds this document:
{
"find": [
"?x"
]
}
async with (await stardust.parse(query_text, "json")) as definition:
try:
async with (await db.query(definition)):
pass
except stardust.StardustError as error:
result = error{
"code": "unbound_variable",
"message": "Unbound_Variable",
"path": null,
"field": null,
"entity": null,
"offset": null,
"status": "invalid_definition"
}Report a missing stored query
try:
async with (await db.query("people/missing")):
pass
except stardust.StardustError as error:
result = error{
"code": "not_found",
"message": "no definition at this path",
"path": "people/missing",
"field": null,
"entity": null,
"offset": null,
"status": "not_found"
}Report a malformed byte at offset zero
malformed_text holds these bytes:
]
try:
async with (await stardust.parse(malformed_text, "dust")):
pass
except stardust.StardustError as error:
result = error{
"code": "invalid_dust",
"message": "Invalid_Syntax at offset 0",
"path": null,
"field": null,
"entity": null,
"offset": 0,
"status": "invalid_argument"
}Report malformed DUST
malformed_text holds these bytes:
[
try:
async with (await stardust.parse(malformed_text, "dust")):
pass
except stardust.StardustError as error:
result = error{
"code": "invalid_dust",
"message": "Unexpected_End at offset 2",
"path": null,
"field": null,
"entity": null,
"offset": 2,
"status": "invalid_argument"
}