Error Handling and Diagnostics#
Most synchronous ovstage calls return an ovstage_api_status_t:
OVSTAGE_OK (0) is success and any non-zero value is an error. Asynchronous
enqueues instead return an ovstage_enqueue_result_t, and completion or
per-op failures surface later through ovstage_wait_op. Distinguish enqueue
success from execution success: OVSTAGE_OK at enqueue means accepted, not
completed.
Status Codes#
Code |
Value |
Meaning |
|---|---|---|
|
0 |
Success. |
|
1 |
A required argument was invalid. |
|
2 |
A handle did not refer to a live object. |
|
3 |
The requested item was not found. |
|
4 |
In INSERT (create-only) mode, a prim already exists at the target path. (A missing item is |
|
5 |
A write/apply targeted an ordinal at or below the write floor. |
|
6 |
The operation is not supported by this build. |
|
7 |
The submission queue is full. |
|
8 |
No further groups to fetch. |
|
9 |
Allocation failed. |
|
10 |
The underlying column layout changed. |
|
11 |
Not ready within the timeout (a wait signal, not a failure). |
|
12 |
The op executed but failed. |
|
99 |
An internal error occurred. |
Turning Codes into Strings#
Three diagnostic accessors exist, with distinct return types and lifetimes:
Accessor |
Returns |
Use |
|---|---|---|
|
static |
Human-readable text for a status code. Vtable-dispatched, so it needs a live instance. |
|
|
The message for a specific failed op. Transient — copy it to retain (refer to String Handling). |
|
|
A free function readable even when |
Checking a Synchronous Call#
// Check a synchronous ovstage call: compare against OVSTAGE_OK and stringify
// failures with ovstage_get_error_string (vtable-dispatched, so it takes the
// instance). The examples fail fast -- print and exit; a real application
// would propagate the error instead.
static void check(ovstage_instance_t* stage, ovstage_api_status_t status, const char* what)
{
if (status == OVSTAGE_OK)
return;
std::fprintf(stderr, "ovstage %s failed (code %u): %s\n", what, status,
stage ? ovstage_get_error_string(stage, status) : "(no instance)");
std::exit(EXIT_FAILURE);
}
Inspecting Per-Op Errors After a Wait#
After a wait, inspect ovstage_op_wait_result_t.error_op_ids /
error_op_id_count and call ovstage_get_last_op_error for each failed id
immediately — the message is invalidated by the next wait on the same thread,
so copy it if you need to keep it.
// Drive an async enqueue to completion. Enqueue success (OVSTAGE_OK) only
// means the op was accepted, so wait on the op id, report any per-op errors
// surfaced by the wait, and retire the op (ovstage_destroy_instance requires
// every op released first). The examples fail fast; a real application would
// propagate the errors instead.
static void waitOp(ovstage_instance_t* stage, ovstage_enqueue_result_t enq, const char* what)
{
check(stage, enq.status, what);
ovstage_op_wait_result_t wait{};
const ovstage_api_status_t code = ovstage_wait_op(stage, enq.op_index, OVSTAGE_TIMEOUT_INFINITE, &wait);
for (size_t i = 0; i < wait.error_op_id_count; ++i)
{
const ovx_string_t e = ovstage_get_last_op_error(stage, wait.error_op_ids[i]);
std::fprintf(stderr, "ovstage %s op %llu failed: %.*s\n", what,
(unsigned long long)wait.error_op_ids[i], (int)e.length, e.ptr ? e.ptr : "");
}
if (wait.error_op_id_count != 0)
std::exit(EXIT_FAILURE);
ovstage_release_op(stage, enq.op_index);
check(stage, code, what);
}
Errors in Python#
Python raises exceptions instead of returning codes:
ovstage.OvstageError for stage operations and ovstage.OvxError for
path-dictionary operations. Both subclass RuntimeError and carry a numeric
code and a message; asynchronous errors are raised from .wait().
# ovstage surfaces failures as exceptions: OvstageError for data-plane ops
# (a numeric .code mapping to ovstage.ErrorCode, plus .message) and OvxError
# for path-dictionary calls. Operation.wait() raises OvstageError if the
# enqueue was rejected, or the op (or its ordinal-keyed dependencies) failed.
def write_checked(stage, query, attr, ordinal, values) -> bool:
try:
stage.write_attribute(query, attr, ordinal=ordinal, tensors=values, is_array=False).wait()
return True
except OvstageError as err:
print(f"ovstage write failed (code {int(err.code)}): {err.message}")
return False
Notes#
OVSTAGE_ERROR_TIMEOUTfromovstage_wait_opis “not ready yet,” not a failure;wait_result.lowest_pending_op_idreports the lowest still-pending op in the chain.ovstage_advance_write_floornever raisesWRITE_FLOOR_VIOLATION— backwards advances clamp rather than error.
Where to Go Next#
String Handling — printing and copying the
ovx_string_tvalues these accessors return.Asynchronous Submit/Observe Model — the enqueue/wait lifecycle that surfaces per-op errors.