Skip to main content
Version: 3.4.0

Python Client Error Codes

All Client methods return a plain int status code. A return value of 0 means success — any negative value indicates an error. The Python binding returns the same integer values as the underlying C++ ClientErrorCode enum.

Error Code Table​

Code nameValueDescription
CL_SUCCESS0Operation completed successfully
CL_ERR_UNKNOWN-1Generic/unexpected error
CL_ERR_INVALID_ARG-2Invalid argument or parameter
CL_ERR_NOT_EXIST-3Chronicle or Story does not exist
CL_ERR_ACQUIRED-4Resource is acquired and cannot be destroyed
CL_ERR_NOT_ACQUIRED-5Resource is not acquired and cannot be released
CL_ERR_CHRONICLE_EXISTS-6Chronicle with that name already exists
CL_ERR_NO_KEEPERS-7No ChronoKeeper nodes available
CL_ERR_NO_CONNECTION-8No connection to ChronoVisor
CL_ERR_NOT_AUTHORIZED-9Operation not authorized
CL_ERR_NO_PLAYERS-10No ChronoPlayer nodes available
CL_ERR_NOT_READER_MODE-11Client is in WRITER_MODE; read operations unavailable
CL_ERR_QUERY_TIMED_OUT-12Replay query or tail-read RPC timed out
CL_ERR_PROTOCOL_VERSION_MISMATCH-13Client and server disagree on the wire-protocol version
CL_ERR_PARTIAL_RESULT-18Query returned fewer records than it should: for a tail read, events left keeper memory between its two phases; for a replay, a keeper missed its fetch deadline or hit its event cap, or an archive file could not be read. The records that came back are valid
CL_ERR_DURABILITY_UNAVAILABLE-19Durable write: the keeper has no WAL, its WAL failed, it is shutting down, or it lacks the durable RPC. Nothing was stored
CL_ERR_DURABILITY_FULL-20Durable write: the keeper's WAL file system is below its reserve, or the keeper holds more unconfirmed data than durable_cap_mb. Nothing was stored
CL_ERR_DURABILITY_UNKNOWN-21Durable write: the event may be stored. event_time holds its timestamp
Reserved range

Codes -14 through -17 are intentionally unassigned. They are reserved for the ingest acceptance-window and collision-policy work developing in parallel, so that branch and this one never assign the same number to different meanings.

Durability error codes​

Only StoryHandle.log_event(log_string, options) with Durability.Durable returns these codes.

ValueWas the event stored?What to do
-19NoRetrying will not help until an operator acts: the keeper runs with the WAL off, its WAL failed and needs a restart, the keeper is shutting down (wait until it has been restarted), or the keeper predates 3.4.0. Returned at once, with no retry.
-20NoRetry later, with a backoff: the WAL's file system is below its reserve or the keeper holds more than durable_cap_mb of chunks the grapher has not confirmed, usually because ChronoGrapher is behind or down.
-21MaybeThe caller decides. Every attempt went unanswered, or an unanswered attempt was followed by -19, -20 or a keeper without the RPC, or the story's keepers left between attempts, or the keeper's WAL failed while writing the event and could not erase it. event_time is the event's timestamp: replay the story over a range that includes it, once the keepers have recovered, and look for your record. A new log_event call creates a second event with a new identity; put your own identifier in the record if repeats must be dropped.

The C++ error codes page gives the causes in full.

Error Handling​

Since the Python binding returns raw integers, check return codes with simple comparisons or a lookup table:

import py_chronolog_client

ERROR_NAMES = {
0: "CL_SUCCESS",
-1: "CL_ERR_UNKNOWN",
-2: "CL_ERR_INVALID_ARG",
-3: "CL_ERR_NOT_EXIST",
-4: "CL_ERR_ACQUIRED",
-5: "CL_ERR_NOT_ACQUIRED",
-6: "CL_ERR_CHRONICLE_EXISTS",
-7: "CL_ERR_NO_KEEPERS",
-8: "CL_ERR_NO_CONNECTION",
-9: "CL_ERR_NOT_AUTHORIZED",
-10: "CL_ERR_NO_PLAYERS",
-11: "CL_ERR_NOT_READER_MODE",
-12: "CL_ERR_QUERY_TIMED_OUT",
-13: "CL_ERR_PROTOCOL_VERSION_MISMATCH",
-18: "CL_ERR_PARTIAL_RESULT",
-19: "CL_ERR_DURABILITY_UNAVAILABLE",
-20: "CL_ERR_DURABILITY_FULL",
-21: "CL_ERR_DURABILITY_UNKNOWN",
}


portal_conf = py_chronolog_client.ClientPortalServiceConf("ofi+sockets", "127.0.0.1", 5555, 55)
client = py_chronolog_client.Client(portal_conf)

ret = client.Connect()
if ret != 0:
print(f"Connect failed: {ERROR_NAMES.get(ret, ret)}")
else:
print("Connected successfully")

ret = client.CreateChronicle("MyChronicle", {}, 1)
if ret == 0 or ret == -6: # success or already exists — both are acceptable
print("Chronicle ready")
else:
print(f"CreateChronicle failed: {ERROR_NAMES.get(ret, ret)}")