gRPC Status Codes

All 17 gRPC status codes with numeric value, HTTP mapping and retry guidance.

Reference for the 17 canonical gRPC status codes from OK (0) to DATA_LOSS (15), with each code's numeric value, equivalent HTTP status, meaning and whether the call is safe to retry. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

How many gRPC status codes are there?

There are 17 canonical codes, numbered 0 through 16. OK is 0 and the highest is UNAUTHENTICATED at 16. Code values are stable and defined in the grpc-status spec.

gRPC status codes explained

Every gRPC call completes with a status consisting of a numeric code and an optional message. Unlike HTTP, gRPC defines a fixed, language-neutral set of 17 codes (0–16) that every implementation shares. This reference lists all of them with their numeric value, the conventional HTTP status they map to in gateways, a plain-language meaning, and whether the call is generally safe to retry.

How it works

gRPC status codes are defined in the grpc-status trailer of every response. Code 0 (OK) means success; any non-zero code is an error. The codes split roughly into three groups:

  • Client errors the caller should fix: INVALID_ARGUMENT (3), NOT_FOUND (5), PERMISSION_DENIED (7), FAILED_PRECONDITION (9), UNAUTHENTICATED (16).
  • Transient errors worth retrying: DEADLINE_EXCEEDED (4), RESOURCE_EXHAUSTED (8), ABORTED (10), UNAVAILABLE (14).
  • Server faults that signal bugs: UNKNOWN (2), INTERNAL (13), DATA_LOSS (15).

When a gRPC service is exposed over HTTP via a gateway, codes map to HTTP statuses by convention — NOT_FOUND becomes 404, UNAVAILABLE becomes 503, and so on. That mapping is shown per row so you can reason about both protocols at once.

Quick reference: all 17 codes

CodeNameHTTP equivalentRetry?
0OK200
1CANCELLED499No
2UNKNOWN500No
3INVALID_ARGUMENT400No
4DEADLINE_EXCEEDED504Maybe (idempotent only)
5NOT_FOUND404No
6ALREADY_EXISTS409No
7PERMISSION_DENIED403No
8RESOURCE_EXHAUSTED429Yes (with backoff)
9FAILED_PRECONDITION400No
10ABORTED409Yes (with backoff)
11OUT_OF_RANGE400No
12UNIMPLEMENTED501No
13INTERNAL500No
14UNAVAILABLE503Yes (with backoff)
15DATA_LOSS500No
16UNAUTHENTICATED401No

Distinguishing the easiest-to-confuse codes

FAILED_PRECONDITION vs ABORTED vs UNAVAILABLE: These three look similar but mean different things. FAILED_PRECONDITION means the system is not in a state that allows the operation — for example, deleting a non-empty directory. ABORTED means a concurrency conflict such as a test-and-set failing or a transaction aborting; the client should usually retry at a higher level. UNAVAILABLE means the server is temporarily down or overloaded and the call never reached application logic.

UNKNOWN vs INTERNAL: UNKNOWN surfaces when a non-gRPC error leaks through without a defined status code — for example, an unhandled exception in middleware. INTERNAL is reserved for serious invariant violations inside a service, like corrupted data or a failed serialisation. Both map to HTTP 500, but INTERNAL signals a bug in the server; UNKNOWN suggests an integration or wiring problem.

CANCELLED vs DEADLINE_EXCEEDED: CANCELLED means the client cancelled the request. DEADLINE_EXCEEDED means the deadline passed before the server completed, but the server may have finished anyway — the state of the operation is ambiguous, which matters for non-idempotent calls.

Retry guidance and example

A safe retry policy retries only idempotent calls that failed with UNAVAILABLE, and uses exponential backoff:

attempt 1 -> wait 100ms
attempt 2 -> wait 200ms
attempt 3 -> wait 400ms (then give up)

Avoid retrying INVALID_ARGUMENT, NOT_FOUND or PERMISSION_DENIED — the inputs must change first. For RESOURCE_EXHAUSTED, honour any retry-delay the server returns rather than hammering it. Use the table above to confirm a code’s number and HTTP equivalent before wiring up interceptors.