Deliver a more consistent user experience by proactively interpreting and responding to errors. Whether you're developing automated cloud workflows or interacting with remote APIs, the Rust client libraries provide ways to gracefully handle errors. This guide explains how to:
- Handle errors: Inspect error types and branch your application logic based
on service status codes, such as creating a missing resource when encountering a
NotFounderror. - Examine error details: Extract and examine rich error details—such as bad request field violations or quota failures—returned by Google Cloud services to troubleshoot API issues and dynamically adjust runtime behavior.
- Resolve binding errors: Interpret and resolve client-side HTTP binding errors caused by invalid or missing request fields to ensure your requests reach the service smoothly.
Prerequisites
This guide uses the Secret Manager service and the Cloud Natural Language API to demonstrate error handling. To run the examples, first:
- Enable the Secret Manager service.
- Enable the Cloud Natural Language API.
- Set up authentication.
Dependencies
Use the following command to add the required dependencies to your Cargo.toml
file:
cargo add google-cloud-secretmanager-v1 google-cloud-gax crc32c google-cloud-language-v2
Handle errors
The Rust client libraries let you surface and react to errors. You might, for example, use error discovery to branch behavior: a common pattern in cloud services is to use a resource as if the container for it existed, only creating the container if you encounter an error. If the container usually exists, this approach is more efficient than checking whether the container exists before making the request.
The following example demonstrates how to handle a missing resource by catching the error when attempting to update a Secret Manager secret—and creating it if it doesn't already exist.
Make an attempt to create a new secret version:
If
update_attemptsucceeds, print the successful result and return:If
update_attemptfails, you must disambiguate the cause of the failure. The request might have failed for many reasons, such as a dropped connection or error with authentication tokens. Retry policies can deal with most of these errors. Look for errors returned by the service:Look for an error that corresponds with a missing secret:
If you have encountered a "not found" error (
Code::NotFound), try to create the secret:Try to add the secret version again. This time, return an error if anything fails:
Code sample: main function (sample)
The complete code for this example is broken into three parts: the main
orchestration function (sample), followed by its two helper methods
(update_attempt and create_secret).
The sample function attempts to add a new version to a secret. It catches the
error returned by the client and checks if the error is a Code::NotFound
error. If the secret is not found, the function creates the initially missing
secret and retries the update.
Code sample: helper method (update_attempt)
The helper method update_attempt tries to add a secret version, calculating
the CRC32c checksum of the payload data:
Code sample: helper method (create_secret)
The helper method create_secret creates a missing secret and configures a
customized retry policy:
Examine error details
Some Google Cloud services include additional error details when requests fail.
To help with troubleshooting, the Rust client libraries include
these details when formatting errors using std::fmt::Display. You can examine
these details and change your application behavior accordingly.
Only errors returned by the service contain detailed information. The client
libraries return a
StatusDetails
enum with the different types of error details.
Extract error details
This example intentionally sends a bad request to the Cloud Natural Language API and examines the resulting error.
Create a client:
Send a request (in this example, a key field is missing):
Extract the error from the result using standard Rust functions. The error type prints all the error details in human-readable form:
The output is similar to the following:
request failed with error Error {
kind: Service {
status_code: Some(
400,
),
headers: Some(
{
"vary": "X-Origin",
"vary": "Referer",
"vary": "Origin,Accept-Encoding",
"content-type": "application/json; charset=UTF-8",
"date": "Sat, 24 May 2025 17:19:49 GMT",
"server": "scaffolding on HTTPServer2",
"x-xss-protection": "0",
"x-frame-options": "SAMEORIGIN",
"x-content-type-options": "nosniff",
"alt-svc": "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000",
"accept-ranges": "none",
"transfer-encoding": "chunked",
},
),
status: Status {
code: InvalidArgument,
message: "One of content, or gcs_content_uri must be set.",
details: [
BadRequest(
BadRequest {
field_violations: [
FieldViolation {
field: "document.content",
description: "Must have some text content to annotate.",
reason: "",
localized_message: None,
_unknown_fields: {},
},
],
_unknown_fields: {},
},
),
],
},
},
}
Programmatically examine error details
Sometimes you might need to examine the error details programmatically. This example traverses the data structure and prints the most relevant fields.
Only errors returned by the service contain detailed information, so first query the error to see if it contains the correct error type. If it does, you can break down some top-level information about the error:
Iterate over the details:
As mentioned earlier, the client libraries return a
StatusDetails
enum with the different types of error details. This example only examines
BadRequest errors:
A BadRequest contains a list of fields that are in violation. You can iterate
and print the details for each:
Such information can be useful during development. Other branches of
StatusDetails, such as
QuotaFailure,
might be useful at runtime to throttle an application.
Expected output
The output from the error details is similar to the following:
status.code=400, status.message=One of content, or gcs_content_uri must be set., status.status=Some("INVALID_ARGUMENT")
the request field document.content has a problem: "Must have some text content to annotate."
Code sample: Examine error details
The sample function sends an intentionally invalid request to the
Cloud Natural Language API to generate a service error. It then catches the error and
programmatically extracts the StatusDetails to inspect and print specific
BadRequest field violations.
Resolve binding errors
When using HTTP to send requests to Google Cloud services, the request uses a Uniform Resource Identifier (URI) to specify a resource. Some RPCs correspond to multiple URIs, and the content of the request determines which URI is used.
The client library considers all possible URIs and only returns a binding error if no URIs work. Typically, this happens when a field is either missing or in an invalid format.
If your request fails to provide fields containing a valid format for any possible URI, you might encounter a binding error:
Error: cannot find a matching binding to send the request: at least one of the
conditions must be met: (1) field `name` needs to be set and match the template:
'projects/*/secrets/*' OR (2) field `name` needs to be set and match the
template: 'projects/*/locations/*/secrets/*'
The preceding example error occurred because the example tries to retrieve the
details of a resource without providing its name. Specifically, the name field
on a GetSecretRequest
is required, but not set by the example:
How to fix binding errors
To fix the error, set the required field so that it matches one of the templates shown in the error message:
'projects/*/secrets/*''projects/*/locations/*/secrets/*'
Either template allows the client library to make a request to the server. For example, the following code matches the first template:
Alternatively, the following code matches the second template:
Interpreting templates
The error message for a binding error includes template strings showing possible
values for the request fields. Most template strings include * and ** as
wildcards to match the field values.
Single wildcard
The * wildcard alone means a non-empty string without a /. It can be thought
of as the regular expression [^/]+.
Here are some examples:
| Template | Input | Match? |
|---|---|---|
* |
simple-string-123 |
true |
projects/* |
projects/p |
true |
projects/*/locations |
projects/p/locations |
true |
projects/*/locations/* |
projects/p/locations/l |
true |
* |
"" (empty) |
false |
* |
string/with/slashes |
false |
projects/* |
projects/ (empty) |
false |
projects/* |
projects/p/ (extra slash) |
false |
projects/* |
projects/p/locations/l |
false |
projects/*/locations |
projects/p |
false |
projects/*/locations |
projects/p/locations/l |
false |
Double wildcard
Less common is the ** wildcard, which means any string. The string can be
empty or contain any number of slashes (/). It can be thought of as the
regular expression .*.
When a template ends in /**, the initial slash is optional.
| Template | Input | Match? |
|---|---|---|
** |
"" |
true |
** |
simple-string-123 |
true |
** |
string/with/slashes |
true |
projects/*/** |
projects/p |
true |
projects/*/** |
projects/p/locations |
true |
projects/*/** |
projects/p/locations/l |
true |
projects/*/** |
locations/l |
false |
projects/*/** |
projects//locations/l |
false |
Inspect binding errors
If you need to inspect the error programmatically, check whether it is a binding
error and downcast it to a BindingError:
What's next
- Learn about Configuring retry policies.