grpcio-status
raw JSON → 1.78.0 verified Tue May 12 auth: no python install: verified quickstart: verified
grpcio-status provides the Python binding for the google.rpc.Status protobuf, enabling rich (structured) error details to be packed into gRPC trailing metadata and unpacked on the client side. It sits on top of grpcio and protobuf, exposing two primary helpers — rpc_status.to_status() and rpc_status.from_call() — both marked EXPERIMENTAL in the source. The package is versioned in strict lockstep with grpcio (current: 1.78.0) and is released on the same cadence, typically every 4–6 weeks.
pip install grpcio-status Common errors
error ModuleNotFoundError: No module named 'grpc_status' ↓
cause This error occurs when the Python interpreter cannot find the `grpc_status` module, typically because the `grpcio-status` package has not been installed or is not accessible in the current Python environment.
fix
Ensure the
grpcio-status package is installed using pip: pip install grpcio-status. If using virtual environments or tools like PySpark, verify that the package is installed in the correct environment being used by the application. error ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts. grpcio-status X.Y.Z requires protobuf<A.B.C,>=D.E.F, but you have protobuf G.H.I which is incompatible. ↓
cause This conflict arises because `grpcio-status` has specific version requirements for the `protobuf` library, and another installed package (or a different version of `protobuf` itself) has conflicting requirements, leading to an incompatible `protobuf` version in the environment.
fix
Try to resolve the dependency conflict by either downgrading or upgrading your
protobuf installation to a version compatible with grpcio-status and other dependent packages. A common strategy is to uninstall protobuf and grpcio-status, then reinstall grpcio-status which should pull a compatible protobuf version, or explicitly install a protobuf version known to work with your grpcio-status version. error AttributeError: 'RpcError' object has no attribute 'code' ↓
cause This error occurs when attempting to access the `code` attribute directly on a `grpc.RpcError` object as a property, rather than calling it as a method.
fix
Access the status code by calling the
code() method on the RpcError object: error.code() instead of error.code. Warnings
breaking grpcio-status>=1.51 requires protobuf>=4.21.6 and is incompatible with any dependency that pins protobuf<4.0.0. Mixing versions causes an unresolvable dependency conflict at install time. ↓
fix Upgrade all protobuf-dependent packages to support protobuf>=4. If a transitive dep cannot be upgraded, pin grpcio-status to a pre-1.51 release (not recommended for production).
breaking grpcio and grpcio-status must share the exact same version. Installing mismatched versions (e.g. grpcio==1.77.0 with grpcio-status==1.78.0) causes runtime AttributeError or silent misbehaviour. ↓
fix Always pin both packages to identical versions: pip install 'grpcio==1.78.0' 'grpcio-status==1.78.0'.
gotcha rpc_status.from_call() returns None — not an empty Status — when the server used set_code()/set_details() instead of abort_with_status(rpc_status.to_status(...)). A failed RPC does not automatically generate a rich status proto. ↓
fix Always null-check the return value of from_call(). On the server, always use context.abort_with_status(rpc_status.to_status(rich_status)) to embed the google.rpc.Status in trailing metadata.
gotcha from_call() raises ValueError if the gRPC call's status code or message text is inconsistent with the values inside the embedded google.rpc.Status proto. This happens when server code sets status code/message separately after packing the proto. ↓
fix Use abort_with_status(rpc_status.to_status(rich_status)) exclusively — it atomically sets code, message, and trailing metadata so they stay consistent.
gotcha Both rpc_status.from_call() and rpc_status.to_status() are explicitly marked EXPERIMENTAL in the gRPC source and documentation; their signatures could change without a major version bump. ↓
fix Track the grpc/grpc GitHub releases page for changes to src/python/grpcio_status/grpc_status/rpc_status.py before upgrading.
gotcha The importable package name is grpc_status (underscore) but the PyPI slug is grpcio-status (hyphen). Confusing them produces a ModuleNotFoundError even when the package is correctly installed. ↓
fix Use: from grpc_status import rpc_status
deprecated grpcio 1.78.0 introduces a new dependency on typing-extensions~=4.13. If your environment pins typing-extensions to an older version the install will fail. ↓
fix Allow typing-extensions>=4.13 in your dependency constraints: pip install 'typing-extensions>=4.13'.
Install
pip install "grpcio-status==1.78.0" "grpcio==1.78.0" "googleapis-common-protos>=1.5.5" Install compatibility verified last tested: 2026-05-12
python os / libc variant status wheel install import disk
3.10 alpine (musl) "grpcio-status==1.78.0" - - 0.26s 41.1M
3.10 alpine (musl) grpcio-status - - 0.27s 41.5M
3.10 slim (glibc) "grpcio-status==1.78.0" - - 0.13s 39M
3.10 slim (glibc) grpcio-status - - 0.13s 39M
3.11 alpine (musl) "grpcio-status==1.78.0" - - 0.69s 43.7M
3.11 alpine (musl) grpcio-status - - 0.69s 44.0M
3.11 slim (glibc) "grpcio-status==1.78.0" - - 0.23s 42M
3.11 slim (glibc) grpcio-status - - 0.27s 42M
3.12 alpine (musl) "grpcio-status==1.78.0" - - 0.86s 35.4M
3.12 alpine (musl) grpcio-status - - 0.82s 35.8M
3.12 slim (glibc) "grpcio-status==1.78.0" - - 0.47s 33M
3.12 slim (glibc) grpcio-status - - 0.47s 34M
3.13 alpine (musl) "grpcio-status==1.78.0" - - 0.81s 35.1M
3.13 alpine (musl) grpcio-status - - 0.79s 35.4M
3.13 slim (glibc) "grpcio-status==1.78.0" - - 0.45s 33M
3.13 slim (glibc) grpcio-status - - 0.46s 33M
3.9 alpine (musl) "grpcio-status==1.78.0" - - 0.20s 40.6M
3.9 alpine (musl) grpcio-status - - 0.20s 40.9M
3.9 slim (glibc) "grpcio-status==1.78.0" - - 0.17s 39M
3.9 slim (glibc) grpcio-status - - 0.18s 39M
Imports
- rpc_status wrong
import grpc_status.rpc_statuscorrectfrom grpc_status import rpc_status - rpc_status.from_call
from grpc_status import rpc_status; status = rpc_status.from_call(rpc_error) - rpc_status.to_status wrong
context.set_code(...); context.set_details(...)correctfrom grpc_status import rpc_status; context.abort_with_status(rpc_status.to_status(rich_status)) - status_pb2.Status
from google.rpc import status_pb2 - error_details_pb2
from google.rpc import error_details_pb2
Quickstart verified last tested: 2026-04-23
# pip install grpcio grpcio-status googleapis-common-protos
import grpc
from grpc_status import rpc_status
from google.rpc import status_pb2, code_pb2, error_details_pb2
from google.protobuf import any_pb2
# --- SERVER SIDE (inside a servicer method) ---
def MyRpc(request, context):
# Build a structured error detail
detail = any_pb2.Any()
detail.Pack(
error_details_pb2.BadRequest(
field_violations=[
error_details_pb2.BadRequest.FieldViolation(
field="name",
description="must not be empty",
)
]
)
)
rich_status = status_pb2.Status(
code=code_pb2.INVALID_ARGUMENT,
message="Invalid request",
details=[detail],
)
# abort_with_status atomically sets code + message + trailing metadata
context.abort_with_status(rpc_status.to_status(rich_status))
# --- CLIENT SIDE ---
def call_rpc(stub):
try:
stub.MyRpc(request=object()) # placeholder
except grpc.RpcError as rpc_error:
# from_call returns None when no rich status was packed
status = rpc_status.from_call(rpc_error)
if status is None:
print("No rich status; plain code:", rpc_error.code())
return
print("gRPC status code:", rpc_error.code())
for detail in status.details:
if detail.Is(error_details_pb2.BadRequest.DESCRIPTOR):
info = error_details_pb2.BadRequest()
detail.Unpack(info)
for v in info.field_violations:
print(f"Field '{v.field}': {v.description}")