gRPC Status Codes

Published
Length
3 min read

Luis Felipe Dias

All posts

You handle grpc status codes by checking the integer code returned with every remote call. Each code tells the client if the request succeeded or why it failed. Teams set up shared error rules so apps can retry or stop right away. When service roles are too broad, a caller can still trigger risky actions. How grpc status codes work in service calls Every remote call ends by returning a status object to the calling app. This object holds an integer code and a short text message. A zero code me

gRPC Security: the complete guide

Architecture patterns, implementation strategies, and security best practices. Delivered to your inbox.

Free white paper. No spam. Unsubscribe anytime.

You handle grpc status codes by checking the integer code returned with every remote call. Each code tells the client if the request succeeded or why it failed. Teams set up shared error rules so apps can retry or stop right away. When service roles are too broad, a caller can still trigger risky actions.

How grpc status codes work in service calls

Every remote call ends by returning a status object to the calling app. This object holds an integer code and a short text message. A zero code means OK and tells the caller the work finished well. Any non-zero number signals a specific problem during the call.

The server picks the code that best matches the failure. For example, Invalid Argument means the client sent bad data in the request. Not Found means the target record does not exist on the server. Already Exists stops a client from creating a duplicate record.

Identity errors use two distinct codes that teams often mix up. Unauthenticated means the caller did not send valid login tokens or keys. Permission Denied means the server knows the caller, but their role lacks rights.

System health issues have their own set of numbers too. Deadline Exceeded fires when a call takes more time than the client allowed. Resource Exhausted means the server ran out of memory, quota, or rate limits. Unavailable tells the client that the target host cannot take traffic right now. Internal marks a bug or crash inside the server app itself.

How teams map errors across services

A mid-tier service often calls a backend database or another internal app. If that downstream call fails, the mid-tier app must pick a status code. Passing the exact downstream code back to the user can confuse the client.

Think about a payment service that calls an internal user service. If the user service returns Not Found, the payment app must translate it. Returning Failed Precondition or Invalid Argument makes more sense to the payment caller. Good error mapping keeps internal system details hidden from outside callers.

gRPC Security: architecture patterns and best practices

Continue reading? Get the full guide.

Free. No spam. Unsubscribe anytime.

Client apps also rely on these codes to run retry rules. A client should never retry Invalid Argument or Permission Denied errors. Those calls will just fail again until someone fixes the request or role. Instead, clients only retry Unavailable or Resource Exhausted after a short wait.

What native error handling solves and what it misses

Standard status codes give teams a clear way to report call results. They help client apps decide when to retry a failed network call. They also tell developers when a service rejects a bad login key.

Still, status codes only report what happened after a rule runs. Service roles usually check who logs in at the start of a session. Once a caller passes that check, the role often grants broad access. Native status checks do not inspect the payload of each individual call.

An engineer or service with a wide role will get an OK status. They can run bulk deletes or read private user records without getting blocked. Even error messages can leak raw emails, phone numbers, or card numbers. Static service roles cannot mask sensitive fields or require approval for risky calls.

Add runtime guardrails and masking beside your databases and APIs

Login rules, role grants, and CI checks govern who connects to your stack. Yet any allowed script, engineer, or AI agent still runs commands with the full scope of its role. For workloads on Postgres, MySQL, SQL Server, MongoDB, ClickHouse, Kubernetes, SSH, or internal HTTP services, hoop.dev sits inline in the protocol beside the service as an open-source proxy, a sidecar for your database or API. On every production query an agent or human runs, hoop.dev decides whether to pass, mask, block, or escalate it for review.

Before a query runs, hoop.dev guardrails check the statement against your rules, an AI Analyzer you configure can score intent or hold risky calls for human approval, and hoop.dev data masking rewrites sensitive fields in responses in memory. Explore the MIT-licensed project on GitHub.

Frequently asked questions

What is the difference between Unauthenticated and Permission Denied?

Unauthenticated means the caller did not provide valid login credentials. Permission Denied means the caller logged in, but their role cannot run that action.

Which grpc status codes should a client app retry?

Clients usually retry Unavailable and sometimes Resource Exhausted after a short delay. Do not retry Invalid Argument, Not Found, or Permission Denied without fixing the request.

Why should services avoid returning Internal for every error?

Returning Internal for all errors hides the real cause from the calling app. The client cannot tell if it sent bad data or if the server crashed.

Save the open-source gateway.

hoop is MIT-licensed infrastructure for controlling how AI agents reach production data. Star hoophq/hoop so you can inspect it, deploy it, or share it when your team starts governing agent access.