This chapter provides an overview of the Google APIs error model as well as general guidance to developers on how to properly generate and handle errors.
Google APIs use a simple protocol-agnostic error model, which allows us to expose a consistent experience across different APIs, API protocols such as gRPC or HTTP, and error contexts (for instance, asynchronous, batch, or workflow errors).
Error Model
The error model is logically defined by
google.rpc.Status
,
an instance of which is returned to the client when an API error occurs. The
following code snippet shows the overall design of the error model:
package google.rpc;
message Status {
// A simple error code that can be easily handled by the client. The
// actual error code is defined by `google.rpc.Code`.
int32 code = 1;
// A developer-facing human-readable error message in English. It should
// both explain the error and offer an actionable resolution to it.
string message = 2;
// Additional error information that the client code can use to handle
// the error, such as retry delay or a help link.
repeated google.protobuf.Any details = 3;
}
Because most Google APIs use resource-oriented API design, the error handling
follows the same design principle by using a small set of standard errors with a
large number of resources. For example, instead of defining different kinds of
"not found" errors, the server uses one standard google.rpc.Code.NOT_FOUND
error code and tells the client which specific resource was not found. The
smaller state space reduces the complexity of documentation, affords better
idiomatic mappings in client libraries, and reduces client logic complexity
while not restricting the inclusion of actionable information.
Error Codes
Google APIs must use the canonical error codes defined by
google.rpc.Code
.
Individual APIs should avoid defining additional error codes, since
developers are very unlikely to write logic to handle a large number of error
codes. For reference, handling an average of 3 error codes per API call would
mean most application logic would just be for error handling, which would not be
a good developer experience.
Error Messages
The error message should help users understand and resolve the API error easily and quickly. In general, consider the following guidelines when writing error messages:
- Do not assume the user is an expert user of your API. Users could be client developers, operations people, IT staff, or end-users of apps.
- Do not assume the user knows anything about your service implementation or is familiar with the context of the errors (such as log analysis).
- When possible, error messages should be constructed such that a technical user (but not necessarily a developer of your API) can respond to the error and correct it.
- Keep the error message brief. If needed, provide a link where a confused reader can ask questions, give feedback, or get more information that doesn't cleanly fit in an error message. Otherwise, use the details field to expand.
Error Details
Google APIs define a set of standard error payloads for error details, which you can find in google/rpc/error_details.proto. These cover the most common needs for API errors, such as quota failure and invalid parameters. Like error codes, error details should use these standard payloads whenever possible.
Additional error detail types should only be introduced if they can assist application code to handle the errors. If the error information can only be handled by humans, rely on the error message content and let developers handle it manually rather than introducing new error detail types.
Here are some example error_details
payloads:
RetryInfo
Describes when clients can retry a failed request, may be returned onCode.UNAVAILABLE
orCode.ABORTED
QuotaFailure
Describes how a quota check failed, may be returned onCode.RESOURCE_EXHAUSTED
BadRequest
Describes violations in a client request, may be returned onCode.INVALID_ARGUMENT
HTTP Mapping
While proto3 messages have native JSON encoding, Google's API Platform uses a different error schema for Google JSON REST APIs for backward compatibility reasons.
Schema:
// The error schema for Google REST APIs. NOTE: this schema is not used for
// other wire protocols.
message Error {
// This message has the same semantics as `google.rpc.Status`. It has an extra
// field `status` for backward compatibility with Google API Client Library.
message Status {
// This corresponds to `google.rpc.Status.code`.
int32 code = 1;
// This corresponds to `google.rpc.Status.message`.
string message = 2;
// This is the enum version for `google.rpc.Status.code`.
google.rpc.Code status = 4;
// This corresponds to `google.rpc.Status.details`.
repeated google.protobuf.Any details = 5;
}
// The actual error payload. The nested message structure is for backward
// compatibility with Google API client libraries. It also makes the error
// more readable to developers.
Status error = 1;
}
Example:
{
"error": {
"code": 401,
"message": "Request had invalid credentials.",
"status": "UNAUTHENTICATED",
"details": [{
"@type": "type.googleapis.com/google.rpc.RetryInfo",
...
}]
}
}
RPC Mapping
Different RPC protocols map the error model differently. For
gRPC, the error model is natively supported by the generated
code and the runtime library in each supported language. You can find out more
in gRPC's API documentation (for example, see gRPC Java's
io.grpc.Status
).
Client Library Mapping
Google client libraries may choose to surface errors differently per language to
be consistent with established idioms. For example, the
google-cloud-go
library will return an error that implements the same interface as
google.rpc.Status
,
while
google-cloud-java
will raise an Exception.
Error Localization
The message
field in
google.rpc.Status
is developer-facing and must be in English.
If a user-facing error message is needed, use
google.rpc.LocalizedMessage
as your details field. While the message field in
google.rpc.LocalizedMessage
can be localized, ensure that the message field in
google.rpc.Status
is in English.
By default, the API service should use the authenticated user’s locale or HTTP
Accept-Language
header to determine the language for the localization.
Handling Errors
Below is a table containing all of the gRPC error codes defined in
google.rpc.Code
and a short description of their cause. To handle an error, you can check the
description for the returned status code and modify your call accordingly.
HTTP | RPC | Description |
---|---|---|
200 | OK |
No error. |
400 | INVALID_ARGUMENT |
Client specified an invalid argument. Check error message and error details for more information. |
400 | FAILED_PRECONDITION |
Request can not be executed in the current system state, such as deleting a non-empty directory. |
400 | OUT_OF_RANGE |
Client specified an invalid range. |
401 | UNAUTHENTICATED |
Request not authenticated due to missing, invalid, or expired OAuth token. |
403 | PERMISSION_DENIED |
Client does not have sufficient permission. This can happen because the OAuth token does not have the right scopes, the client doesn't have permission, or the API has not been enabled for the client project. |
404 | NOT_FOUND |
A specified resource is not found, or the request is rejected by undisclosed reasons, such as whitelisting. |
409 | ABORTED |
Concurrency conflict, such as read-modify-write conflict. |
409 | ALREADY_EXISTS |
The resource that a client tried to create already exists. |
429 | RESOURCE_EXHAUSTED |
Either out of resource quota or reaching rate limiting. The client should look for google.rpc.QuotaFailure error detail for more information. |
499 | CANCELLED |
Request cancelled by the client. |
500 | DATA_LOSS |
Unrecoverable data loss or data corruption. The client should report the error to the user. |
500 | UNKNOWN |
Unknown server error. Typically a server bug. |
500 | INTERNAL |
Internal server error. Typically a server bug. |
501 | NOT_IMPLEMENTED |
API method not implemented by the server. |
503 | UNAVAILABLE |
Service unavailable. Typically the server is down. |
504 | DEADLINE_EXCEEDED |
Request deadline exceeded. This will happen only if the caller sets a deadline that is shorter than the method's default deadline (i.e. requested deadline is not enough for the server to process the request) and the request did not finish within the deadline. |
Error Retries
Clients may retry on 503 UNAVAILABLE errors with exponential backoff. The minimum delay should be 1s unless it is documented otherwise.
For 429 RESOURCE_EXHAUSTED errors, the client may retry at the higher level with minimum 30s delay. Such retries are only useful for long running background jobs.
For all other errors, retry may not be applicable - first ensure your request is idempotent, and see the error message for guidance.
Error Propagation
If your API service depends on other services, you should not blindly propagate errors from those services to your clients. When translating errors, we suggest the following:
- Hide implementation details and confidential information.
- Adjust the party responsible for the error. For example, a server that
receives an
INVALID_ARGUMENT
error from another service should propagate anINTERNAL
to its own caller.
Generating Errors
If you are a server developer, you should generate errors with enough information to help client developers understand and address the problem. At the same time, you must be aware of the security and privacy of the user data, and avoid disclosing sensitive information in the error message and error details, since errors are often logged and may be accessible by others. For example, an error message like "Client IP address is not on whitelist 128.0.0.0/8" exposes information about the server-side policy, which may not be accessible to the user.
To generate proper errors, you first need to be familiar with google.rpc.Code
to
choose the most suitable error code for each error condition. A server
application may check multiple error conditions in parallel, and return the
first one.
The following table lists each error code and an example of a good error message.
HTTP | RPC | Example Error Message |
---|---|---|
400 | INVALID_ARGUMENT |
Request field x.y.z is xxx, expected one of [yyy, zzz]. |
400 | FAILED_PRECONDITION |
Resource xxx is a non-empty directory, so it cannot be deleted. |
400 | OUT_OF_RANGE |
Parameter 'age' is out of range [0, 125]. |
401 | UNAUTHENTICATED |
Invalid authentication credentials. |
403 | PERMISSION_DENIED |
Permission 'xxx' denied on file 'yyy'. |
404 | NOT_FOUND |
Resource 'xxx' not found. |
409 | ABORTED |
Couldn’t acquire lock on resource ‘xxx’. |
409 | ALREADY_EXISTS |
Resource 'xxx' already exists. |
429 | RESOURCE_EXHAUSTED |
Quota limit 'xxx' exceeded. |
499 | CANCELLED |
Request cancelled by the client. |
500 | DATA_LOSS |
See note. |
500 | UNKNOWN |
See note. |
500 | INTERNAL |
See note. |
501 | NOT_IMPLEMENTED |
Method 'xxx' not implemented. |
503 | UNAVAILABLE |
See note. |
504 | DEADLINE_EXCEEDED |
See note. |
NOTE: Since the client cannot fix the server error, it is not useful to
generate additional error details. To avoid leaking sensitive information under
error conditions, it is recommended not to generate any error message and only
generate google.rpc.DebugInfo
error details. The DebugInfo
is specially
designed only for server-side logging, and must not be sent to client.
The google.rpc
package defines a set of standard error payloads, which are
preferred to custom error payloads. The following table lists each error code
and its matching standard error payload, if applicable.
HTTP | RPC | Recommended Error Detail |
---|---|---|
400 | INVALID_ARGUMENT |
google.rpc.BadRequest |
400 | FAILED_PRECONDITION |
google.rpc.PreconditionFailure |
400 | OUT_OF_RANGE |
google.rpc.BadRequest |
401 | UNAUTHENTICATED |
|
403 | PERMISSION_DENIED |
|
404 | NOT_FOUND |
google.rpc.ResourceInfo |
409 | ABORTED |
|
409 | ALREADY_EXISTS |
google.rpc.ResourceInfo |
429 | RESOURCE_EXHAUSTED |
google.rpc.QuotaFailure |
499 | CANCELLED |
|
500 | DATA_LOSS |
|
500 | UNKNOWN |
|
500 | INTERNAL |
|
501 | NOT_IMPLEMENTED |
|
503 | UNAVAILABLE |
|
504 | DEADLINE_EXCEEDED |