Using absl::Status and absl::StatusOr for C++ Error Handling: A Complete Guide

Use absl::Status to signal success or failure with error codes, and absl::StatusOr<T> to return either a value or an error, enabling explicit error handling without exceptions.

The absl::Status and absl::StatusOr<T> utilities in the abseil/abseil-cpp repository provide a robust, exception-free mechanism for handling errors in modern C++. These types implement the "return-error-or-value" pattern popularized by Google's internal codebase, offering lightweight semantics that encourage explicit error checking while maintaining zero-overhead abstractions.

Understanding absl::Status

In absl/status/status.h, absl::Status is implemented as a lightweight object that carries an absl::StatusCode and an optional message string. It serves as the fundamental currency for signaling operation success or failure throughout Abseil-based codebases.

Core API and Success Semantics

Success is represented by absl::OkStatus(), which returns a status with code kOk. The class provides a mirror of absl::StatusCode semantics through key accessors:

  • ok() – Returns true if the status code is kOk.
  • code() – Retrieves the absl::StatusCode enum value.
  • message() – Returns the error message string (empty for OK statuses).

The type is cheap to copy and can be returned from any function that only needs to signal success or failure without transporting a value.

Source Location Tracking

Both Status and StatusOr expose AddSourceLocation() and WithSourceLocation() methods defined in absl/status/status.h. These allow callers to attach call-site information for richer diagnostics, particularly useful when propagating errors up the stack:

return absl::NotFoundError("file not found")
    .WithSourceLocation();  // Attaches caller location automatically

Understanding absl::StatusOr

Defined in absl/status/statusor.h, absl::StatusOr<T> is a discriminated union that holds either a value of type T or a non-OK Status. This pattern eliminates the need for output parameters or exceptions when returning values that might fail to generate.

Value vs. Error Contract

The fundamental contract is presence of a value ↔ ok() == true. When the operation succeeds, the object stores the constructed T; otherwise, it stores a Status indicating the error. The internal implementation in absl/status/internal/statusor_internal.h manages this union efficiently, storing the Status inline to avoid heap allocation when holding a value.

Accessing Values and Handling Errors

StatusOr<T> provides multiple accessors for safe value extraction:

  • ok() – Tests whether the object contains a value.
  • status() – Retrieves the stored Status (useful for error propagation).
  • value() – Returns the value or throws absl::BadStatusOrAccess if exceptions are enabled and the status is not OK.
  • operator* / operator-> – Provide convenient value access after an ok() check.
  • value_or(default) – Returns the contained value or a supplied default if the status is not OK.
  • IgnoreError() – Silences "unused-status" warnings when the caller intentionally discards an error.

The type is marked with ABSL_MUST_USE_RESULT (expanding to [[nodiscard]] on supported compilers) in absl/base/attributes.h, preventing accidental discarding of error information.

Key Architectural Features

The implementation provides several guarantees critical for high-performance C++:

Zero-allocation on success – When StatusOr<T> holds a value, the internal error storage is kept in a small inline representation, avoiding heap allocation entirely.

Conversion flexibility – The class provides converting constructors and assignments for compatible types, as well as in-place construction via std::in_place.

Thread-safe copying – The type is copyable and movable as long as T satisfies the corresponding operations, with no internal synchronization required.

Practical Implementation Examples

The following patterns demonstrate idiomatic usage according to the abseil/abseil-cpp source:

#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/log/log.h"

// Returns either an int or an error
absl::StatusOr<int> ParseInt(absl::string_view text) {
  int value;
  if (absl::SimpleAtoi(text, &value)) {
    return value;  // Implicit construction from T
  }
  return absl::InvalidArgumentError("not an integer");
}

// Consumer code with explicit checking
absl::StatusOr<int> result = ParseInt("42");
if (result.ok()) {
  LOG(INFO) << "Parsed value: " << *result;  // operator* after ok()
} else {
  LOG(ERROR) << "Parse failed: " << result.status();
}

// Using value_or for safe defaults
int safe = ParseInt("abc").value_or(0);

// Error propagation with source location
absl::StatusOr<std::string> LoadFile(absl::string_view path) {
  if (/* simulated IO error */ false) {
    return absl::NotFoundError("file not found")
        .WithSourceLocation();
  }
  return std::string("file contents");
}

// Chaining with early return
absl::StatusOr<std::string> content = LoadFile("data.txt");
if (!content.ok()) return content.status();  // Propagate error

Summary

  • absl::Status (in absl/status/status.h) signals success/failure via error codes, with absl::OkStatus() representing success.
  • absl::StatusOr<T> (in absl/status/statusor.h) transports either a value or an error status,强制执行 explicit checking through [[nodiscard]] semantics.
  • Access values using ok() followed by operator* or operator->, or use value_or() for default fallbacks.
  • Zero-allocation guarantees and inline storage make StatusOr suitable for performance-critical paths.
  • Source location tracking via WithSourceLocation() aids debugging without macro magic.

Frequently Asked Questions

What is the difference between absl::Status and absl::StatusOr?

absl::Status only indicates success or failure via error codes and messages, while absl::StatusOr<T> is a discriminated union that either contains a value of type T or a non-OK status. Use Status for void functions that might fail, and StatusOr when you need to return a computed value or an error.

How do I handle errors without exceptions using StatusOr?

Check ok() before accessing the value, or use value_or() to provide a default. For error propagation, call status() to extract the underlying Status and return it upstream. The ABSL_MUST_USE_RESULT attribute ensures the compiler warns you if you accidentally ignore a returned error.

Does absl::StatusOr allocate memory on the heap?

No. The implementation uses inline storage for the Status object when a value is present, resulting in zero heap allocation on the success path. This is managed internally through the variant storage logic in absl/status/internal/statusor_internal.h.

How do I attach source location information to errors?

Call WithSourceLocation() on any absl::Status or absl::StatusOr to automatically capture the current file and line number. This information is stored within the status object and can be logged or serialized for debugging distributed systems.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →