# Abseil Canonical Status Error Codes: Complete Guide to absl::StatusCode Usage

> Master absl::StatusCode usage with this guide to canonical error codes. Learn when to use each of the 17 standardized codes for portable error semantics across libraries and networks.

- Repository: [Abseil/abseil-cpp](https://github.com/abseil/abseil-cpp)
- Tags: getting-started
- Published: 2026-07-14

---

**The canonical `absl::StatusCode` enum defines 17 standardized error codes in [`absl/status/status.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/status/status.h) that map to the gRPC/Google RPC error space, enabling portable error semantics across libraries and network boundaries.**

The `absl::Status` class is the primary error‑handling type in the Abseil C++ library (`abseil/abseil-cpp`). Every non‑OK status carries a **canonical error code** that allows callers—whether in‑process or remote—to understand failure modes without parsing custom strings. These codes are defined in [[`absl/status/status.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/status/status.h)](https://github.com/abseil/abseil-cpp/blob/master/absl/status/status.h) (lines 78‑104) and correspond directly to the Google RPC error space.

## Canonical Status Error Codes Reference

The following table lists every `absl::StatusCode` value, its semantic meaning as documented in the Abseil source, and the specific scenario where it should be selected.

| Code | Meaning | When to Use |
|------|---------|-------------|
| **`kOk`** | Success – not an error. | Return `absl::OkStatus()` or a default‑constructed `absl::Status` for successful operations. |
| **`kCancelled`** | The operation was cancelled, typically by the caller. | Use when a client explicitly aborts a request, such as cancelling a file download. |
| **`kUnknown`** | An unknown error occurred; used as a fallback. | Use only when the underlying system cannot provide a better classification. |
| **`kInvalidArgument`** | Caller supplied an invalid argument. | Use for validation failures that are *intrinsic* to the argument itself (e.g., malformed filename). |
| **`kDeadlineExceeded`** | A deadline expired before the operation could complete. | Use when a timeout is reached, even if the operation later completes successfully. |
| **`kNotFound`** | Requested entity (file, directory, etc.) was not found. | Use when a lookup fails because the target does not exist. |
| **`kAlreadyExists`** | The entity a caller tried to create already exists. | Use for “create” operations that would result in a duplicate. |
| **`kPermissionDenied`** | Caller lacks permission for the operation. | Use when the request is well‑formed but the caller is not authorized. |
| **`kResourceExhausted`** | Some resource has been exhausted. | Use for quota limits, out‑of‑memory conditions, or disk‑full scenarios. |
| **`kFailedPrecondition`** | System is not in a state required for the operation. | Use when the caller could correct the state, but a simple retry would not help (e.g., non‑empty directory for `rmdir`). |
| **`kAborted`** | Operation aborted due to a concurrency issue. | Use for optimistic‑concurrency failures (e.g., transaction conflicts) that require a higher‑level retry. |
| **`kOutOfRange`** | Operation attempted past a valid range. | Use when the error is *range*‑specific and the caller can advance to the next range (e.g., read past EOF). |
| **`kUnimplemented`** | Operation not implemented or supported. | Use for stubbed or platform‑specific features that are absent. |
| **`kInternal`** | Internal error – invariants violated. | Use for serious bugs that should be logged and alerted on immediately. |
| **`kUnavailable`** | Service temporarily unavailable (transient). | Use for transient failures where a retry with back‑off is appropriate. |
| **`kDataLoss`** | Unrecoverable data loss or corruption. | Use for catastrophic data‑integrity problems; attach alerts. |
| **`kUnauthenticated`** | Request lacks valid authentication credentials. | Use when the caller cannot be identified; differs from `kPermissionDenied`. |

## Creating Statuses with Canonical Codes

Abseil provides convenience factory functions in [`absl/status/status.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/status/status.h) to ensure consistency. These factories return an `absl::Status` with the appropriate canonical code and the provided message string.

```cpp
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include <iostream>

absl::Status ReadFile(absl::string_view path) {
  if (path.empty()) {
    // Convenience factory for kInvalidArgument
    return absl::InvalidArgumentError("path must not be empty");
  }
  
  // ... attempt to open file ...
  
  if (!file_exists(path)) {
    // Convenience factory for kNotFound
    return absl::NotFoundError(absl::StrCat("file not found: ", path));
  }
  
  return absl::OkStatus();
}

```

Available factories include `absl::CancelledError()`, `absl::UnknownError()`, `absl::DeadlineExceededError()`, and others corresponding to each canonical code.

## Checking Error Codes in Practice

To inspect a status without exposing the raw enum values, use the predicate helpers declared at lines 108‑136 of [`absl/status/status.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/status/status.h) (e.g., `absl::IsNotFound()`, `absl::IsInvalidArgument()`). For complex dispatch, switch on `status.code()` directly.

```cpp
absl::Status s = ReadFile("/tmp/data.txt");

// Method 1: Predicate helpers
if (absl::IsNotFound(s)) {
  std::cerr << "Please create the file first.\n";
} else if (absl::IsInvalidArgument(s)) {
  std::cerr << "Bad request: " << s.message() << "\n";
}

// Method 2: Switch on the canonical code
switch (s.code()) {
  case absl::StatusCode::kPermissionDenied:
    std::cerr << "Access denied.\n";
    break;
  case absl::StatusCode::kUnavailable:
    std::cerr << "Service temporarily down; consider retry.\n";
    break;
  default:
    std::cerr << "Unhandled error: " << s << "\n";
    break;
}

```

## Distinguishing Between Similar Codes

Several canonical codes describe overlapping failure modes. Select the most specific code to aid caller recovery.

### kFailedPrecondition vs. kInvalidArgument

**`kInvalidArgument`** indicates that an argument is inherently invalid (e.g., negative size for a buffer) regardless of system state. **`kFailedPrecondition`** indicates the system is not in the required state for the operation (e.g., deleting a non‑empty directory), even though the argument itself might be valid in another context.

### kPermissionDenied vs. kUnauthenticated

**`kUnauthenticated`** means the caller cannot be identified (e.g., missing or invalid credentials). **`kPermissionDenied`** means the caller is known but lacks authorization for the specific action. Return `kUnauthenticated` before checking permissions.

### kUnavailable vs. kAborted

**`kUnavailable`** signals transient service disruptions (network timeouts, server downtime) where a retry with exponential back‑off is appropriate. **`kAborted`** signals concurrency failures (transaction conflicts) that require a higher‑level retry or reconciliation strategy, not just a simple re‑send.

## Summary

- Prefer the most specific canonical `absl::StatusCode` available rather than generic fallbacks like `kUnknown`.
- Use convenience factories (e.g., `absl::NotFoundError()`) defined in [`absl/status/status.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/status/status.h) to ensure consistency with the canonical codes.
- Distinguish between caller errors (`kInvalidArgument`, `kNotFound`) and system errors (`kInternal`, `kUnavailable`) when selecting codes.
- Preserve canonical codes when propagating errors across RPC boundaries to maintain semantic meaning; use payloads for additional context if needed.

## Frequently Asked Questions

### What is the difference between kFailedPrecondition and kInvalidArgument?

`kInvalidArgument` indicates that an argument is inherently invalid (e.g., malformed syntax), regardless of system state. `kFailedPrecondition` indicates the system is not in the required state for the operation (e.g., deleting a non‑empty directory), even though the argument itself might be valid in another context.

### When should I use kUnavailable instead of kAborted?

Use `kUnavailable` for transient service disruptions where a retry with back‑off is likely to succeed, such as network timeouts or server downtime. Use `kAborted` for concurrency failures like transaction conflicts that require a higher‑level retry or reconciliation strategy.

### How do I check for specific error codes without comparing raw enum values?

Abseil provides predicate functions such as `absl::IsNotFound()`, `absl::IsInvalidArgument()`, and `absl::IsUnavailable()` declared in [[`absl/status/status.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/status/status.h)](https://github.com/abseil/abseil-cpp/blob/master/absl/status/status.h) (lines 108‑136). These provide type‑safe checks without exposing the underlying `StatusCode` enum.

### Can I define custom error codes beyond the canonical set?

No. The `absl::StatusCode` enum is closed and maps directly to the gRPC wire format. If you need application‑specific detail, attach a payload to the `absl::Status` object or use the message string, but keep the canonical code to ensure interoperability.