Skip to content

Error handling

The three execution modes

Every builder’s .execute() method supports three modes that control how per-record errors are surfaced:

ModeJavaPythonBehaviorBest for
Defaultexecute()await … .execute()Single-key: throws immediately. Batch: errors embedded in streamSimple cases
In-stream errorsexecute(ErrorStrategy.IN_STREAM)await … .execute(on_error=ErrorStrategy.IN_STREAM)All errors embedded as RecordResult entries in the streamUniform handling of single + batch
Error callbackexecute(errorHandler)await … .execute(on_error=<callable>)Errors dispatched to callback, excluded from streamLogging, fire-and-forget

Java exposes the same three modes via overloads of execute() and executeAsync(). The Python SDK uses await … .execute(on_error=…) as the entry point for the async surface (aerospike_sdk.aio.*); the synchronous surface (aerospike_sdk.sync.*) wraps the same builders behind blocking .execute(on_error=…) calls. Either way there is no separate executeAsync() — choosing async vs sync is a matter of which session/client class you import.

Mode 1: Default (execute())

Single-key operations throw on failure:

try {
session.update(users.id("no-such-key"))
.bin("name").setTo("Alice")
.execute();
} catch (AerospikeException e) {
System.out.println("Failed: " + e.getResultCode()); // 2 = KEY_NOT_FOUND_ERROR
}

Batch operations embed errors in the stream — they do not throw:

RecordStream stream = session
.update(users.id("exists"))
.bin("count").add(1)
.update(users.id("no-such-key"))
.bin("count").add(1)
.execute();
stream.forEach(result -> {
if (result.isOk()) {
System.out.println(result.key().userKey + ": success");
} else {
System.out.println(result.key().userKey + ": " + result.message());
}
});

Mode 2: ErrorStrategy.IN_STREAM

Forces all errors (including single-key) into the stream. Useful when you want uniform handling regardless of key count:

RecordStream stream = session.update(users.id("no-such-key"))
.bin("name").setTo("Alice")
.execute(ErrorStrategy.IN_STREAM);
stream.forEach(result -> {
if (!result.isOk()) {
System.out.println("Error: " + result.resultCode() + " - " + result.message());
}
});

Mode 3: ErrorHandler callback

Errors are dispatched to the handler and excluded from the stream. The stream contains only successful results:

RecordStream stream = session
.upsert(users.id("u1")).bin("name").setTo("Alice")
.upsert(users.id("u2")).bin("name").setTo("Bob")
.execute((key, index, exception) ->
System.err.println("Failed key " + key.userKey +
" at index " + index + ": " + exception.getMessage())
);
// stream contains only successful results
stream.forEach(result -> {
System.out.println(result.key().userKey + ": OK");
});

Inspecting RecordResult

Every result in the stream is a RecordResult. Key members:

JavaPythonReturnsThrows?
isOk()is_ok (attribute)true if result_code == OKNo
resultCode()result_code (attribute)Integer result codeNo
message()(use exception / result_code)Human-readable error message (or null/None)No
orThrow()or_raise()self if OK, throws otherwiseYes
recordOrThrow()record_or_raise()The Record if OK, throws otherwiseYes
recordOrNull()record (attribute, may be None)The Record or null/None — does not throwNo
asBoolean()as_bool()true if OK, false if KEY_NOT_FOUND, throws otherwiseConditionally
key()key (attribute; user value via key.value)The Key for this operationNo
index()index (attribute)Position in the batch (0-based)No
inDoubt()in_doubt (attribute)Whether the write may have succeeded on the serverNo
exception()exception (attribute)The AerospikeException / AerospikeError if available, or NoneNo

Using failures() to isolate errors

RecordStream.failures() consumes the entire source stream and returns only the failed results. In Java this is a new RecordStream; in Python it is an awaitable that resolves to list[RecordResult].

RecordStream stream = session
.update(users.id("u1")).bin("count").add(1)
.update(users.id("u2")).bin("count").add(1)
.update(users.id("missing")).bin("count").add(1)
.execute(ErrorStrategy.IN_STREAM);
RecordStream errors = stream.failures();
errors.forEach(failure ->
System.err.println("Failed: " + failure.key().userKey + "" + failure.message())
);

Note: failures() is a terminal-style helper — it drains and exhausts the source stream and returns the failures fully in memory (a new RecordStream in Java; a list[RecordResult] in Python). In Python it does not call stream.close() for you; if you need to release client/server resources promptly, call stream.close() (or wrap the work in try / finally) after collecting the failures.

Existence checks

The asBoolean() / as_bool() method translates OK → true, KEY_NOT_FOUND → false, any other error → throws:

boolean exists = session.exists(users.id("user-1"))
.execute()
.getFirstBoolean()
.orElse(false);

Decision guide

ScenarioRecommended mode
Simple single-key read/writeexecute() + try/catch
Batch where all failures are fatalexecute() + iterate and check isOk() / is_ok
Batch where you need consistent handlingexecute(ErrorStrategy.IN_STREAM) (Java) / execute(on_error=ErrorStrategy.IN_STREAM) (Python)
Batch where failures should be logged but not blockexecute(errorHandler) (Java) / execute(on_error=<callable>) (Python)
Need to collect all failures for retryIN_STREAM mode + .failures()
Feedback

Was this page helpful?

What type of feedback are you giving?

What would you like us to know?

+Capture screenshot

Can we reach out to you?