Overview
The Status class encapsulates the result of an operation. It may indicate success or an error with an associated error message. Multiple threads can invoke const methods on a Status without external synchronization.
Status Codes
Code Enum
enum Code : unsigned char {
kOk = 0,
kNotFound = 1,
kCorruption = 2,
kNotSupported = 3,
kInvalidArgument = 4,
kIOError = 5,
kMergeInProgress = 6,
kIncomplete = 7,
kShutdownInProgress = 8,
kTimedOut = 9,
kAborted = 10,
kBusy = 11,
kExpired = 12,
kTryAgain = 13,
kCompactionTooLarge = 14,
kColumnFamilyDropped = 15,
kMaxCode
};
SubCode Enum
enum SubCode : unsigned char {
kNone = 0,
kMutexTimeout = 1,
kLockTimeout = 2,
kLockLimit = 3,
kNoSpace = 4,
kDeadlock = 5,
kStaleFile = 6,
kMemoryLimit = 7,
kSpaceLimit = 8,
kPathNotFound = 9,
KMergeOperandsInsufficientCapacity = 10,
kManualCompactionPaused = 11,
kOverwritten = 12,
kTxnNotPrepared = 13,
kIOFenced = 14,
kMergeOperatorFailed = 15,
kMergeOperandThresholdExceeded = 16,
kPrefetchLimitReached = 17,
kNotExpectedCodePath = 18,
kCompactionAborted = 19,
kMaxSubCode
};
Severity Enum
enum Severity : unsigned char {
kNoError = 0,
kSoftError = 1,
kHardError = 2,
kFatalError = 3,
kUnrecoverableError = 4,
kMaxSeverity
};
Creating Status Objects
Success Status
Status s = Status::OK();
assert(s.ok());
Error Status Constructors
NotFound
static Status NotFound(const Slice& msg, const Slice& msg2 = Slice());
static Status NotFound(SubCode msg = kNone);
return Status::NotFound("Key not in database");
return Status::NotFound(); // Fast path without malloc
Corruption
static Status Corruption(const Slice& msg, const Slice& msg2 = Slice());
static Status Corruption(SubCode msg = kNone);
Indicates data corruption detected.
NotSupported
static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice());
static Status NotSupported(SubCode msg = kNone);
Operation is not supported by this implementation.
InvalidArgument
static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice());
static Status InvalidArgument(SubCode msg = kNone);
Invalid arguments provided to the operation.
IOError
static Status IOError(const Slice& msg, const Slice& msg2 = Slice());
static Status IOError(SubCode msg = kNone);
if (read_failed) {
return Status::IOError("Failed to read file", filename);
}
Incomplete
static Status Incomplete(const Slice& msg, const Slice& msg2 = Slice());
static Status Incomplete(SubCode msg = kNone);
Operation did not complete (e.g., compaction was aborted).
ShutdownInProgress
static Status ShutdownInProgress(SubCode msg = kNone);
static Status ShutdownInProgress(const Slice& msg, const Slice& msg2 = Slice());
Aborted
static Status Aborted(SubCode msg = kNone);
static Status Aborted(const Slice& msg, const Slice& msg2 = Slice());
Operation was aborted.
Busy
static Status Busy(SubCode msg = kNone);
static Status Busy(const Slice& msg, const Slice& msg2 = Slice());
Resource is busy and temporarily could not be acquired.
TimedOut
static Status TimedOut(SubCode msg = kNone);
static Status TimedOut(const Slice& msg, const Slice& msg2 = Slice());
TryAgain
static Status TryAgain(SubCode msg = kNone);
static Status TryAgain(const Slice& msg, const Slice& msg2 = Slice());
Operation failed but may succeed if re-attempted.
Specialized Error Constructors
NoSpace
static Status NoSpace();
static Status NoSpace(const Slice& msg, const Slice& msg2 = Slice());
Out of disk space error (IOError with kNoSpace subcode).
MemoryLimit
static Status MemoryLimit();
static Status MemoryLimit(const Slice& msg, const Slice& msg2 = Slice());
Memory limit exceeded (Aborted with kMemoryLimit subcode).
SpaceLimit
static Status SpaceLimit();
static Status SpaceLimit(const Slice& msg, const Slice& msg2 = Slice());
Space limit exceeded (IOError with kSpaceLimit subcode).
PathNotFound
static Status PathNotFound();
static Status PathNotFound(const Slice& msg, const Slice& msg2 = Slice());
File or directory not found (IOError with kPathNotFound subcode).
Checking Status
Returns true if the status indicates success
Status s = db->Get(read_options, key, &value);
if (s.ok()) {
// Operation succeeded
} else {
// Handle error
}
Error Type Checking
IsNotFound
Returns true if status indicates a NotFound error.
Status s = db->Get(read_options, "key", &value);
if (s.IsNotFound()) {
// Key doesn't exist, this is expected
} else if (!s.ok()) {
// Some other error occurred
}
IsCorruption
bool IsCorruption() const;
Returns true if status indicates a Corruption error.
IsNotSupported
bool IsNotSupported() const;
Returns true if status indicates a NotSupported error.
IsInvalidArgument
bool IsInvalidArgument() const;
Returns true if status indicates an InvalidArgument error.
IsIOError
Returns true if status indicates an IOError.
IsIncomplete
bool IsIncomplete() const;
Returns true if status indicates Incomplete.
IsShutdownInProgress
bool IsShutdownInProgress() const;
IsTimedOut
IsAborted
IsBusy
IsTryAgain
Specialized Error Checking
IsNoSpace
Returns true if status indicates an out-of-space I/O error.
IsMemoryLimit
bool IsMemoryLimit() const;
Returns true if status indicates memory limit error.
IsPathNotFound
bool IsPathNotFound() const;
Returns true if status indicates path not found error.
IsManualCompactionPaused
bool IsManualCompactionPaused() const;
Returns true if manual compaction was paused.
code
Returns the primary status code
subcode
Returns the status subcode for additional error context
severity
Severity severity() const;
Returns the error severity level
getState
const char* getState() const;
Returns a C-style string containing the error message
ToString
std::string ToString() const;
Returns a string representation suitable for printing. Returns “OK” for success.
Status s = db->Put(write_options, key, value);
if (!s.ok()) {
std::cerr << "Put failed: " << s.ToString() << std::endl;
}
Status Manipulation
UpdateIfOk
Status& UpdateIfOk(Status&& s);
Status& UpdateIfOk(const Status& s);
Status to potentially adopt
Returns reference to this Status (allows chaining)
Override this status with another, unless this status is already non-ok. Left-most error takes precedence.
Status overall_status = Status::OK();
overall_status.UpdateIfOk(db->Put(options, "key1", "value1"))
.UpdateIfOk(db->Put(options, "key2", "value2"))
.UpdateIfOk(db->Put(options, "key3", "value3"));
// overall_status will be the first error encountered, or OK if all succeeded
CopyAppendMessage
static Status CopyAppendMessage(const Status& s,
const Slice& delim,
const Slice& msg);
Create a new Status by appending additional message to an existing Status.
Unchecked Status Handling
PermitUncheckedError
inline void PermitUncheckedError() const;
Explicitly mark that you are intentionally ignoring this error. Makes it easy to search for error swallowing.
Status s = db->Delete(write_options, key);
if (s.IsNotFound()) {
// Key didn't exist, that's fine
s.PermitUncheckedError();
}
When ROCKSDB_ASSERT_STATUS_CHECKED is defined, Status objects must be checked before being destroyed, otherwise the program will abort.
Common Usage Patterns
Basic Error Handling
Status s = db->Get(read_options, key, &value);
if (!s.ok()) {
if (s.IsNotFound()) {
// Handle missing key
return default_value;
} else {
// Handle other errors
LOG(ERROR) << "Get failed: " << s.ToString();
return s;
}
}
// Use value
Multiple Operations
Status BatchWrite(DB* db, const std::vector<std::pair<std::string, std::string>>& kvs) {
WriteBatch batch;
for (const auto& kv : kvs) {
batch.Put(kv.first, kv.second);
}
Status s = db->Write(WriteOptions(), &batch);
if (!s.ok()) {
LOG(ERROR) << "Batch write failed: " << s.ToString();
}
return s;
}
Accumulating Errors
Status ProcessRecords(DB* db) {
Status result = Status::OK();
result.UpdateIfOk(ProcessRecord1(db));
result.UpdateIfOk(ProcessRecord2(db));
result.UpdateIfOk(ProcessRecord3(db));
// result contains first error, or OK if all succeeded
return result;
}
Retrying on Specific Errors
Status WriteWithRetry(DB* db, const std::string& key, const std::string& value) {
const int max_retries = 3;
for (int i = 0; i < max_retries; i++) {
Status s = db->Put(WriteOptions(), key, value);
if (s.ok()) {
return s;
}
if (s.IsBusy() || s.IsTryAgain()) {
// Wait and retry
std::this_thread::sleep_for(std::chrono::milliseconds(100 * (i + 1)));
continue;
}
// Don't retry other errors
return s;
}
return Status::TimedOut("Max retries exceeded");
}