[google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
message when an API error occurs, and must use the canonical error codes defined in [google.rpc.Code](https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto)
. More information about the particular codes is available in the [gRPC status code documentation](https://github.com/grpc/grpc/blob/master/doc/statuscodes.md).
+
+Error messages **should** help a reasonably technical user _understand_ and _resolve_ the issue, and **should not** assume that the user is an expert in your particular API. Additionally, error messages **must not** assume that the user will know anything about its underlying implementation.
-Error messages **should** help a reasonably technical user _understand_ and
-_resolve_ the issue, and **should not** assume that the user is an expert in
-your particular API. Additionally, error messages **must not** assume that the
-user will know anything about its underlying implementation.
+Error messages **should** be brief but actionable. Any extra information **should** be provided in the `details `field. If even more information is necessary, you **should** provide a link where a reader can get more information or ask questions to help resolve the issue. It is also important to [set the right tone](https://developers.google.com/tech-writing/error-messages/set-tone) when writing messages.
-Error messages **should** be brief but actionable. Any extra information
-**should** be provided in the `details` field. If even more information is
-necessary, you **should** provide a link where a reader can get more
-information or ask questions to help resolve the issue.
+### Error Response
+#### JSON representation
-A JSON representation of an error response might look like the
-following:
+A JSON representation of an error response might look like the following example.
-
+For the purposes of following best practices, it’s helpful to break the error response into sections. Note that the order in which you write the error message is often different from how the error is presented to users.
-```json
+```
+<<<<<[google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
as follows:
+
+* present a developer-facing, human-readable "debug message"
+* present the message in the service's native language
+* explain both the error and offer an actionable resolution to it ([citation](https://cloud.google.com/apis/design/errors#error_model))
+
+**Note:** Sometimes a service will elect to always present `Status.message` in English rather than the application's native language so that messages are easily searchable in common knowledge bases, such as StackOverflow™.
+
+Details of this object are summarized in the table that follows.
+
+Important points:
+
+* This `message` string is considered a problem description. It is intended for human developers to understand the problem and is more detailed than [ErrorInfo.reason](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L57)
, discussed in the next section.
+* Use simple descriptive language that is easy to understand (without technical jargon) to clearly state the problem that results in an error.
+* For pre-existing (brownfield) APIs, the information in google.rpc.Status
already exists and can’t be changed. In this case, do not edit anything in this google.rpc.Status
, because some users might have automation running against the pre-existing content. For example, any changes in text for the message
string could cause breakages. For more information, see [Changing Error Messages](#changing-error-messages).
+
+[google.rpc.Status payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
+
+Field + | +Description + | +
code int32
+ |
+ The status code, which should be an enum value of google.rpc.Code.
+ +Example: 429 + |
+
message string
+ |
+ A developer-facing error message, which should be in English. Any user-facing error message should be located in the LocalizedMessage payload.
+ +Example message: "The zone 'us-east1-a' does not have enough resources available to fulfill the request. Try a different zone, or try again later." + |
+
details Object (repeated)
+ |
+ Text
+ +Example: Described in the ErrorDetails section. + |
+
+ | ++ | +
[BadRequest](https://github.com/googleapis/googleapis/blob/477a59d764428136ba1d857a9633c0d231de6efa/google/rpc/error_details.proto#L168-L218)
message in the details
, but there may be a BadRequest
and a [PreconditionFailure](https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L139-L166)
.
+
+##### ErrorInfo payload
+
+The [ErrorInfo](https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L27-L76)
message is the required way to send a machine-readable identifier. All error responses must include an ErrorInfo
payload in details
. Variable information should be included in metadata
in ErrorInfo
and must be included if it appears within an error message.
+
+When introducing an error that represents a failure scenario that did not previously occur for the service, the payload **must** include `ErrorInfo` and any variables found in dynamic segments of the error message **must** be present in `ErrorInfo.metadata` (See [Dynamic variables](#dynamic-variables).
+
+**Note:** `ErrorInfo` represents a special case. There **must** be exactly one `ErrorInfo`. It is required.
+
+[ErrorInfo Payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L51)
+
+
+Field + | +Description + | +
reason string
+ |
+ A short snake_case description of why the error occurred. Error reasons are unique within a particular domain of errors.
+ +The error reason must do the following:
|
+
domain string
+ |
+ The logical grouping to which the reason belongs. The error domain is typically the registered service name of the tool or product that generated the error. The domain must be a globally unique value.
+
+Example: " |
+
metadata map
+ |
+ Additional structured details about this error, which should provide important context for customers to identify resolution steps. Keys should match /[a-zA-Z0-9-_]/ and be limited to 64 characters in length. When identifying the current value of an exceeded limit, the units should be contained in the key, not the value.
+
+Example: +For guidance on using the metadata map, see Dynamic Variables. + |
+
[google.rpc.LocalizedMessage](https://github.com/googleapis/googleapis/blob/e9897ed945336e2dc967b439ac7b4be6d2c62640/google/rpc/error_details.proto#L275-L285)
in Status.details
. The value of the Status.message string
should be presented in the service's native language in the LocalizedMessage.message
string, while also ensuring that the locale
string shows the correct language.
-Each type of detail payload **must** be included at most once. For
-example, there **must not** be more than one [`BadRequest`][BadRequest]
-message in the `details` field, but there **may** be a `BadRequest` and
-a [`PreconditionFailure`][PreconditionFailure].
+##### LocalizedMessage payload
-**Note:** `ErrorInfo` represents a special case. There **must** be exactly one
-`ErrorInfo`. It is required.
+The LocalizedMessage payload **should** contain the complete resolution to the error. If more information is needed than can fit in this payload, then additional resolution information **must** be provided in the HelpLink payload. See the [HelpLink payload](#helplink-payload) section for guidance.
-### Error messages
+For pre-existing (brownfield) APIs, the content in this `message` string will differ from the `message` string in `google.rpc.status`.
+
+[LocalizedMessage Payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L277)
+
+Field + | +Description + | +
locale string
+ |
+ The locale that follows the specification defined in IETF bcp47 (Tags for Identifying Languages).
+ +Example: “en-US” , “fr-CH”, “es-MX” + |
+
message string
+ |
+ The error message that the customer will receive through their chosen service, which should include a brief description of the error and a call to action to resolve the error. The message should include, where needed, data provided in other fields such as metadata.
+ + +Give users clear and concise instructions for resolving the error, which must be explicit as possible; for example: +
-For each error, the service **must** populate the `message` field on
-[`google.rpc.Status`][Status]. This error message,
+
-- is a developer-facing, human-readable "debug message"
-- is presented in the service's native language
-- both explains the error and offers an actionable resolution to it
- ([citation](https://cloud.google.com/apis/design/errors#error_model))
+
+If the error resolution exceeds the number of characters supported in the problem description
+( |
+
Field + | +Description + | +
description string
+ |
+ Describes what the link offers.
+ + Example: “Troubleshooting documentation for STOCKOUT errors” + |
+
url string
+ |
+ The URL of the link. For error documentation this must follow the standardized format listed in the following example.
+ +Example: https://cloud.google.com/PRODUCT/docs/ERROR-REASON + |
+
[google.rpc.LocalizedMessage](https://github.com/googleapis/googleapis/blob/e9897ed945336e2dc967b439ac7b4be6d2c62640/google/rpc/error_details.proto#L275-L285)
to [Status.details](https://github.com/googleapis/googleapis/blob/aeae5ea2b01ece6c0cee046ae84b881cdc62b95d/google/rpc/status.proto#L46-L48)
. LocalizedMessage
is meant for displaying messages to end users.
-When adding an error message via `LocalizedMessage`, `ErrorInfo`
-**must** be introduced either before or at the same time. If there are
-dynamic segments found in the text, the values of these variables
-**must** be included in `ErrorInfo.metadata`. See, "[Dynamic
-variables](#dynamic-variables)".
+The error message presented in `LocalizedMessage.message` **should** be the same as `Status.message` or it **should** be an alternate message. Add as much information as the consumer of the error needs to resolve the error, but succinctly.
-**Warning:** If `LocalizedMessage` is released without `ErrorInfo`, the
-same [concerns](#status-message-warning) regarding client misuse of
-textual error messages apply.
+Reasons to present the same error message in both locations include the following:
-#### Dynamic variables
+* The service plans to localize either immediately or in the near future. See, "[Localization](https://google.aip.dev/193#localization)".
+* This practice enables clients to find an error message consistently in one location, `LocalizedMessaage.message`, across all methods of the API Service.
-The best, actionable error messages include dynamic segments. These
-variable parts of the message are specific to a particular request.
-Consider the following example:
+Reasons to present an error message in `LocalizedMessage.message` that differs from `Status.message` include the following:
-> The Book, "The Great Gatsby", is unavailable at the Library, "Garfield
-> East". It is expected to be available again on 2199-05-13.
+* The service requires an end-user-facing error message that differs from the "debug message".
+* Ongoing, iterative error message improvements are expected.
-The preceding error message is made actionable by the context, both that
-originates from the request, the title of the Book and the name of the
-Library, and by the information that is known only by the service, i.e.
-the expected return date of the Book.
+When including `LocalizedMessage`, both `locale` and `message` **must** be populated. If the service is to be localized, the value of `locale` **must** change dynamically. See [Localization](https://google.aip.dev/193#localization). Otherwise, `locale` **must** always present the service's default locale; for example, "en-US".
-All dynamic variables found in error messages **must** also be present
-in the `map[google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
object.
### Permission Denied
-If the user does not have permission to access the resource or parent,
-regardless of whether or not it exists, the service **must** error with
-`PERMISSION_DENIED` (HTTP 403). Permission **must** be checked prior to checking
-if the resource or parent exists.
+If the user does not have permission to access the resource or parent, regardless of whether or not it exists, the service **must** error with `PERMISSION_DENIED` (HTTP 403). Permission **must** be checked prior to checking if the resource or parent exists.
-If the user does have proper permission, but the requested resource or parent
-does not exist, the service **must** error with `NOT_FOUND` (HTTP 404).
+If the user does have proper permission, but the requested resource or parent does not exist, the service **must** error with `NOT_FOUND` (HTTP 404).
## Rationale
### Requiring ErrorInfo
-`ErrorInfo` is required because it further identifies an error. With
-only approximately twenty [available values][Code] for `Status.status`,
-it is difficult to disambiguate one error from another across an entire
-[API Service][API Service].
+`ErrorInfo` is required because it further identifies an error. With only approximately twenty [available values](https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto) for `Status.status`, it is difficult to disambiguate one error from another across an entire [API Service](https://cloud.google.com/apis/design/glossary#api_service).
-Also, error messages often contain dynamic segments that express
-variable information, so there needs to be machine readable component of
-*every* error response that enables clients to use such information
-programmatically.
+Also, error messages often contain dynamic segments that express variable information, so there needs to be machine-readable component of _every_ error response that enables clients to use such information programmatically.
### LocalizedMessage
-`LocalizedMessage` was selected as the location to present alternate
-error messages. This is desirable when clients need to display a crafted
-error message directly to end users. `LocalizedMessage` can be used with
-a static `locale`. This may seem misleading, but it allows the service
-to eventually localize without having to duplicate or move the error
-message, which would be a backwards incompatible change.
+`LocalizedMessage` was selected as the location to present alternate error messages. This is desirable when clients need to display a crafted error message directly to end users. `LocalizedMessage` can be used with a static `locale`. This may seem misleading, but it allows the service to eventually localize without having to duplicate or move the error message, which would be a backwards incompatible change.
+
+### Updating Status.Message
+
+**Because Status.Message is part of the API contract**, avoid updating it entirely in favor of updating LocalizedMessage; for example, clients often perform string matches on the text to differentiate one error for another and even parse the error message to extract variables from dynamic segments.
## Further reading
-- For which error codes to retry, see [AIP-194](https://aip.dev/194).
-- For how to retry errors in client libraries, see
- [AIP-4221](https://aip.dev/client-libraries/4221).
+* For which error codes to retry, see [AIP-194](https://aip.dev/194).
+* For how to retry errors in client libraries, see [AIP-4221](https://aip.dev/client-libraries/4221).
## Changelog
+- **2024-01-10**: Incorporate guidance for writing effective messages.
- **2023-05-17**: Change the recommended language for `Status.message`
to be the service's native language rather than English.
- **2023-05-17**: Specify requirements for changing error messages.
From 9839e15a26ed933dfc93723f16f1dc4185bc4cb8 Mon Sep 17 00:00:00 2001
From: jschneider11 <38144056+jschneider11@users.noreply.github.com>
Date: Mon, 22 Jan 2024 19:15:56 +0000
Subject: [PATCH 02/11] Updated tables to Markdown.
---
aip/general/0193.md | 355 +++++++++++++++++++++++---------------------
1 file changed, 189 insertions(+), 166 deletions(-)
diff --git a/aip/general/0193.md b/aip/general/0193.md
index 994456ffc..db168f0c9 100644
--- a/aip/general/0193.md
+++ b/aip/general/0193.md
@@ -90,46 +90,38 @@ Important points:
* Use simple descriptive language that is easy to understand (without technical jargon) to clearly state the problem that results in an error.
* For pre-existing (brownfield) APIs, the information in google.rpc.Status
already exists and can’t be changed. In this case, do not edit anything in this google.rpc.Status
, because some users might have automation running against the pre-existing content. For example, any changes in text for the message
string could cause breakages. For more information, see [Changing Error Messages](#changing-error-messages).
-[google.rpc.Status payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
-
-Field - | -Description - | -
code int32
- |
- The status code, which should be an enum value of google.rpc.Code.
- -Example: 429 - |
-
message string
- |
- A developer-facing error message, which should be in English. Any user-facing error message should be located in the LocalizedMessage payload.
- -Example message: "The zone 'us-east1-a' does not have enough resources available to fulfill the request. Try a different zone, or try again later." - |
-
details Object (repeated)
- |
- Text
- -Example: Described in the ErrorDetails section. - |
-
- | -- | -
Field - | -Description - | -
reason string
- |
- A short snake_case description of why the error occurred. Error reasons are unique within a particular domain of errors.
- -The error reason must do the following:
|
-
domain string
- |
- The logical grouping to which the reason belongs. The error domain is typically the registered service name of the tool or product that generated the error. The domain must be a globally unique value.
-
-Example: " |
-
metadata map
- |
- Additional structured details about this error, which should provide important context for customers to identify resolution steps. Keys should match /[a-zA-Z0-9-_]/ and be limited to 64 characters in length. When identifying the current value of an exceeded limit, the units should be contained in the key, not the value.
-
-Example: -For guidance on using the metadata map, see Dynamic Variables. - |
-
Field - | -Description - | -
locale string
- |
- The locale that follows the specification defined in IETF bcp47 (Tags for Identifying Languages).
- -Example: “en-US” , “fr-CH”, “es-MX” - |
-
message string
- |
- The error message that the customer will receive through their chosen service, which should include a brief description of the error and a call to action to resolve the error. The message should include, where needed, data provided in other fields such as metadata.
- - -Give users clear and concise instructions for resolving the error, which must be explicit as possible; for example: -
-
-
-
-
-If the error resolution exceeds the number of characters supported in the problem description
-( |
-
Field - | -Description - | -
description string
- |
- Describes what the link offers.
- - Example: “Troubleshooting documentation for STOCKOUT errors” - |
-
url string
- |
- The URL of the link. For error documentation this must follow the standardized format listed in the following example.
- -Example: https://cloud.google.com/PRODUCT/docs/ERROR-REASON - |
-
[ErrorInfo.reason](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L57)
, discussed in the next section.
* Use simple descriptive language that is easy to understand (without technical jargon) to clearly state the problem that results in an error.
* For pre-existing (brownfield) APIs, the information in google.rpc.Status
already exists and can’t be changed. In this case, do not edit anything in this google.rpc.Status
, because some users might have automation running against the pre-existing content. For example, any changes in text for the message
string could cause breakages. For more information, see [Changing Error Messages](#changing-error-messages).
-[google.rpc.Status payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
+##### [google.rpc.Status payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
-Fields, field descriptions, and examples:
+Details of this object are summarized in the following fields, field descriptions, and examples:
* `code int32`
* The status code, which **should** be an enum value of [google.rpc.Code](https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto).
@@ -121,106 +115,33 @@ When introducing an error that represents a failure scenario that did not previo
[ErrorInfo Payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L51)
-Fields, field descriptions, and examples:
-
-*
-
-+---------------------------------------+---------------------------------------+
-| **Field** | **Description** |
-+---------------------------------------+---------------------------------------+
-| `reason string` | A short snake_case description of why |
-| | the error occurred. Error reasons are |
-| | unique within a particular domain of |
-| | errors. |
-| | |
-| | The error reason **must** do the |
-| | following: |
-| | |
-| | - Be at most 63 characters and |
-| | match a regular expression of |
-| | |
-| | \`\[A-Z\]\[A-Z0-9\_\]+\[A-Z0-9\]\`, |
-| | which represents |
-| | UPPER_SNAKE_CASE. |
-| | |
-| | - Be unique and consumable by |
-| | machine actors for automation |
-| | |
-| | - Be meaningful enough for a human |
-| | reader to understand what the |
-| | reason refers to |
-| | |
-| | - Map to one and only one cause, |
-| | That is, avoid making machine |
-| | actors reliant on ErrorInfo. |
-| | |
-| | *Example*: CPU_AVAILABILITY |
-| | |
-| | Distill your error message into |
-| | its simplest form. For example, |
-| | if your error message is: |
-| | |
-| | `The |
-| | Book, "The Great Gatsby", is unavaila |
-| | ble at the Library, "Garfield East".` |
-| | |
-| | `It is expected |
-| | to be available again on 2199-05-13.` |
-| | |
-| | The `reason string `could be one |
-| | of the following text examples in |
-| | UPPER_SNAKE_CASE: |
-| | |
-| | - UNAVAILABLE |
-| | |
-| | - NO_STOCK |
-| | |
-| | - CHECKED_OUT |
-| | |
-| | - AVAILABILITY_ERROR |
-| | |
-| | In contrast, using any of the |
-| | following reasons breaches |
-| | the intended formatting and |
-| | is not recommended: |
-| | |
-| | - noBooks |
-| | - |
-| | THE_BOOK_YOU_WANT_IS_NOT_AVAILABLE |
-| | - ERROR |
-| | - librariesAreGreat |
-+---------------------------------------+---------------------------------------+
-| `domain string` | The logical grouping to which the |
-| | `reason` belongs. The error domain is |
-| | typically the registered service name |
-| | of the tool or product that generated |
-| | the error. The domain must be a |
-| | globally unique value. |
-| | |
-| | *Example*: |
-| | \"`pubsub.googleapis.com`\". |
-+---------------------------------------+---------------------------------------+
-| `metadata map` | Additional structured details about |
-| | this error, which **should** provide |
-| | important context for customers to |
-| | identify resolution steps. Keys |
-| | **should** match /\[a-zA-Z0-9-\_\]/ |
-| | and be limited to 64 characters in |
-| | length. When identifying the current |
-| | value of an exceeded limit, the units |
-| | **should** be contained in the key, |
-| | not the value. |
-| | |
-| | *Example*: |
-| | `"zone": "us |
-| | -east1-a", "vmType": "e2-medium", "at |
-| | tachment": "local-ssd=3,nvidia-t4=2"` |
-| | |
-| | For guidance on using the metadata |
-| | map, see [Dynamic |
-| | Variables](#dynamic-variables). |
-+---------------------------------------+---------------------------------------+
-
+Details of this object are summarized in the following fields, field descriptions, and examples:
+
+* `reason string`
+ * A short snake_case description of why the error occurred. Error reasons are unique within a particular domain of errors.
+ The error reason **must** do the following:
+ * Be at most 63 characters and match a regular expression of \`\[A-Z\]\[A-Z0-9\_\]+\[A-Z0-9\]\`, which represents UPPER_SNAKE_CASE.
+ * Be unique and consumable by machine actors for automation.
+ * Be meaningful enough for a human reader to understand what the reason refers to.
+ * Map to one and only one cause, That is, avoid making machine actors reliant on ErrorInfo.
+ * *Example*: CPU_AVAILABILITY
+ * Distill your error message into its simplest form. For example, if your error message is: `The Book, "The Great Gatsby", is unavailable at the Library, "Garfield East". It is expected to be available again on 2199-05-13.` The `reason string `could be one of the following text examples in UPPER_SNAKE_CASE:
+ * UNAVAILABLE
+ * NO_STOCK
+ * CHECKED_OUT
+ * AVAILABILITY_ERROR
+ * In contrast, using any of the following reasons breaches the intended formatting and is not recommended:
+ * noBooks
+ * THE_BOOK_YOU_WANT_IS_NOT_AVAILABLE
+ * ERROR
+ * librariesAreGreat
+* `domain string`
+ * The logical grouping to which the `reason` belongs. The error domain is typically the registered service name of the tool or product that generated the error. The domain must be a globally unique value.
+ * *Example*: \"`pubsub.googleapis.com`\".
+* `metadata map`
+ * Additional structured details about this error, which **should** provide important context for customers to identify resolution steps. Keys **should** match /\[a-zA-Z0-9-\_\]/ and be limited to 64 characters in length. When identifying the current value of an exceeded limit, the units **should** be contained in the key, not the value.
+ * *Example*: `"zone": "us-east1-a", "vmType": "e2-medium", "attachment": "local-ssd=3,nvidia-t4=2"`
+ * For guidance on using the metadata map, see [Dynamic Variables](#dynamic-variables).
##### Dynamic variables
@@ -269,50 +190,16 @@ For pre-existing (brownfield) APIs, the content in this `message` string will di
[LocalizedMessage Payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L277)
-+---------------------------------------+---------------------------------------+
-| **Field** | **Description** |
-+---------------------------------------+---------------------------------------+
-| `locale string` | The locale that follows the |
-| | specification defined in [IETF |
-| | bcp47](https:// |
-| | www.rfc-editor.org/rfc/bcp/bcp47.txt) |
-| | (Tags for Identifying Languages). |
-| | |
-| | *Example*: "en-US" , "fr-CH", "es-MX" |
-+---------------------------------------+---------------------------------------+
-| `message string` | The error message that the customer |
-| | will receive through their chosen |
-| | service, which **should** include a |
-| | brief description of the error and a |
-| | call to action to resolve the error. |
-| | The message **should** include, where |
-| | needed, data provided in other fields |
-| | such as metadata. |
-| | |
-| | Give users clear and concise |
-| | instructions for resolving the error, |
-| | which **must** be explicit as |
-| | possible; for example: |
-| | |
-| | `Consider trying your request in the |
-| | [google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
message when an API error occurs, and must use the canonical error codes defined in [google.rpc.Code](https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto)
. More information about the particular codes is available in the [gRPC status code documentation](https://github.com/grpc/grpc/blob/master/doc/statuscodes.md).
-
-Error messages **should** help a reasonably technical user _understand_ and _resolve_ the issue, and **should not** assume that the user is an expert in your particular API. Additionally, error messages **must not** assume that the user will know anything about its underlying implementation.
-
-Error messages **should** be brief but actionable. Any extra information **should** be provided in the `details `field. If even more information is necessary, you **should** provide a link where a reader can get more information or ask questions to help resolve the issue. It is also important to [set the right tone](https://developers.google.com/tech-writing/error-messages/set-tone) when writing messages.
+Services **must** return a
+[google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
+message when an API error occurs, and must use the canonical
+error codes defined in
+[google.rpc.Code](https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto)
.
+More information about the particular codes is available in the
+[gRPC status code documentation](https://github.com/grpc/grpc/blob/master/doc/statuscodes.md).
+
+Error messages **should** help a reasonably technical user *understand* and
+*resolve* the issue, and **should not** assume that the user is an expert in
+your particular API. Additionally, error messages **must not** assume that the
+user will know anything about its underlying implementation.
+
+Error messages **should** be brief but actionable. Any extra information
+**should** be provided in the `details`field. If even more information is
+necessary, you **should** provide a link where a reader can get more information
+or ask questions to help resolve the issue. It is also important to
+[set the right tone](https://developers.google.com/tech-writing/error-messages/set-tone)
+when writing messages.
### Error Response
#### JSON representation
-A JSON representation of an error response might look like the following example.
+A JSON representation of an error response might look like the following
+example.
-For the purposes of following best practices, it’s helpful to break the error response into sections. Note that the order in which you write the error message is often different from how the error is presented to users.
+For the purposes of following best practices, it’s helpful to break the error
+response into sections. Note that the order in which you write the error message
+is often different from how the error is presented to users.
```json
{
@@ -65,89 +86,159 @@ For the purposes of following best practices, it’s helpful to break the error
#### google.rpc.Status
-Services must return a [google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto) message when an API error occurs. For each error, the service **must** populate the `message` string in [google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
as follows:
+Services must return a
+[google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
+message when an API error occurs. For each error, the service **must** populate
+the `message` string in
+[google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
+as follows:
* present a developer-facing, human-readable "debug message"
* present the message in the service's native language
-* explain both the error and offer an actionable resolution to it ([citation](https://cloud.google.com/apis/design/errors#error_model))
+* explain both the error and offer an actionable resolution to it
+ ([citation](https://cloud.google.com/apis/design/errors#error_model))
-**Note:** Sometimes a service will elect to always present `Status.message` in English rather than the application's native language so that messages are easily searchable in common knowledge bases, such as StackOverflow™.
+**Note:** Sometimes a service will elect to always present `Status.message` in
+English rather than the application's native language so that messages are
+easily searchable in common knowledge bases, such as StackOverflow™.
Important points:
-* This `message` string is considered a problem description. It is intended for human developers to understand the problem and is more detailed than [ErrorInfo.reason](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L57)
, discussed in the next section.
-* Use simple descriptive language that is easy to understand (without technical jargon) to clearly state the problem that results in an error.
-* For pre-existing (brownfield) APIs, the information in google.rpc.Status
already exists and can’t be changed. In this case, do not edit anything in this google.rpc.Status
, because some users might have automation running against the pre-existing content. For example, any changes in text for the message
string could cause breakages. For more information, see [Changing Error Messages](#changing-error-messages).
-
-##### [google.rpc.Status payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
-
-Details of this object are summarized in the following fields, field descriptions, and examples:
-
-* `code int32`
- * The status code, which **should** be an enum value of [google.rpc.Code](https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto).
- * *Example*: 429
-* `message string`
- * A developer-facing error message, which **should** be in English. Any user-facing error message **should** be located in the LocalizedMessage payload.
- * *Example message*: \"The zone \'us-east1-a\' does not have enough resources available to fulfill the request. Try a different zone, or try again later.\"
-* `details Object (repeated)`
- * Text
- * *Example*: Described in the [ErrorDetails](#error-details) section.
+* This `message` string is considered a problem description. It is intended
+ for human developers to understand the problem and is more detailed than
+ [ErrorInfo.reason](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L57)
,
+ discussed in the next section.
+* Use simple descriptive language that is easy to understand (without
+ technical jargon) to clearly state the problem that results in an error.
+* For pre-existing (brownfield) APIs, the information in
+ google.rpc.Status
already exists and can’t be changed. In this
+ case, do not edit anything in this google.rpc.Status
, because
+ some users might have automation running against the pre-existing content.
+ For example, any changes in text for the message
string could
+ cause breakages. For more information, see
+ [Changing Error Messages](#changing-error-messages).
+
+##### [google.rpc.Status payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
+
+Details of this object are summarized in the following fields, field
+descriptions, and examples:
+
+* `code int32`
+ * The status code, which **should** be an enum value of
+ [google.rpc.Code](https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto).
+ * *Example*: 429
+* `message string`
+ * A developer-facing error message, which **should** be in English. Any
+ user-facing error message **should** be located in the LocalizedMessage
+ payload.
+ * *Example message*: \"The zone \'us-east1-a\' does not have enough
+ resources available to fulfill the request. Try a different zone, or try
+ again later.\"
+* `details Object (repeated)`
+ * Text
+ * *Example*: Described in the [ErrorDetails](#error-details) section.
#### [ErrorDetails](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto)
-Google defines a set of [standard detail payloads](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto) for error details, which cover most common needs for API errors. Services **should** use these standard detail payloads when feasible.
+Google defines a set of
+[standard detail payloads](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto)
+for error details, which cover most common needs for API errors. Services
+**should** use these standard detail payloads when feasible.
-Structured details with machine-readable identifiers **must** be used if users will need to write code against a specific aspect of the error. Error message strings **may** change over time; however, if an error message does not have a machine-readable identifier _in addition to_ the `code` string, changing the error message **must** be considered a backwards-incompatible change.
+Structured details with machine-readable identifiers **must** be used if users
+will need to write code against a specific aspect of the error. Error message
+strings **may** change over time; however, if an error message does not have a
+machine-readable identifier *in addition to* the `code` string, changing the
+error message **must** be considered a backwards-incompatible change.
-For the purpose of this discussion, the ErrorDetails section contains three payloads: `ErrorInfo`, `LocalizedMessage`, and `HelpLink`.
+For the purpose of this discussion, the ErrorDetails section contains three
+payloads: `ErrorInfo`, `LocalizedMessage`, and `HelpLink`.
##### Uniqueness
-Each type of detail payload **must** be included at most once. For example, there **must not** be more than one [BadRequest](https://github.com/googleapis/googleapis/blob/477a59d764428136ba1d857a9633c0d231de6efa/google/rpc/error_details.proto#L168-L218)
message in the details
, but there may be a BadRequest
and a [PreconditionFailure](https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L139-L166)
.
+Each type of detail payload **must** be included at most once. For example,
+there **must not** be more than one
+[BadRequest](https://github.com/googleapis/googleapis/blob/477a59d764428136ba1d857a9633c0d231de6efa/google/rpc/error_details.proto#L168-L218)
+message in the details
, but there may be a
+BadRequest
and a
+[PreconditionFailure](https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L139-L166)
.
##### ErrorInfo payload
-The [ErrorInfo](https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L27-L76)
message is the required way to send a machine-readable identifier. All error responses must include an ErrorInfo
payload in details
. Variable information should be included in metadata
in ErrorInfo
and must be included if it appears within an error message.
+The
+[ErrorInfo](https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L27-L76)
+message is the required way to send a machine-readable identifier. All error
+responses must include an ErrorInfo
payload in
+details
. Variable information should be included
+in metadata
in ErrorInfo
and must be
+included if it appears within an error message.
-When introducing an error that represents a failure scenario that did not previously occur for the service, the payload **must** include `ErrorInfo` and any variables found in dynamic segments of the error message **must** be present in `ErrorInfo.metadata` (See [Dynamic variables](#dynamic-variables).
+When introducing an error that represents a failure scenario that did not
+previously occur for the service, the payload **must** include `ErrorInfo` and
+any variables found in dynamic segments of the error message **must** be present
+in `ErrorInfo.metadata` (See [Dynamic variables](#dynamic-variables).
-**Note:** `ErrorInfo` represents a special case. There **must** be exactly one `ErrorInfo`. It is required.
+**Note:** `ErrorInfo` represents a special case. There **must** be exactly one
+`ErrorInfo`. It is required.
[ErrorInfo Payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L51)
-Details of this object are summarized in the following fields, field descriptions, and examples:
-
-* `reason string`
- * A short snake_case description of why the error occurred. Error reasons are unique within a particular domain of errors.
- The error reason **must** do the following:
- * Be at most 63 characters and match a regular expression of \`\[A-Z\]\[A-Z0-9\_\]+\[A-Z0-9\]\`, which represents UPPER_SNAKE_CASE.
- * Be unique and consumable by machine actors for automation.
- * Be meaningful enough for a human reader to understand what the reason refers to.
- * Map to one and only one cause, That is, avoid making machine actors reliant on ErrorInfo.
- * *Example*: CPU_AVAILABILITY
- * Distill your error message into its simplest form. For example, if your error message is: `The Book, "The Great Gatsby", is unavailable at the Library, "Garfield East". It is expected to be available again on 2199-05-13.` The `reason string `could be one of the following text examples in UPPER_SNAKE_CASE:
- * UNAVAILABLE
- * NO_STOCK
- * CHECKED_OUT
- * AVAILABILITY_ERROR
- * In contrast, using any of the following reasons breaches the intended formatting and is not recommended:
- * noBooks
- * THE_BOOK_YOU_WANT_IS_NOT_AVAILABLE
- * ERROR
- * librariesAreGreat
-* `domain string`
- * The logical grouping to which the `reason` belongs. The error domain is typically the registered service name of the tool or product that generated the error. The domain must be a globally unique value.
- * *Example*: \"`pubsub.googleapis.com`\".
-* `metadata map`
- * Additional structured details about this error, which **should** provide important context for customers to identify resolution steps. Keys **should** match /\[a-zA-Z0-9-\_\]/ and be limited to 64 characters in length. When identifying the current value of an exceeded limit, the units **should** be contained in the key, not the value.
- * *Example*: `"zone": "us-east1-a", "vmType": "e2-medium", "attachment": "local-ssd=3,nvidia-t4=2"`
- * For guidance on using the metadata map, see [Dynamic Variables](#dynamic-variables).
+Details of this object are summarized in the following fields, field
+descriptions, and examples:
+
+* `reason string`
+ * A short snake_case description of why the error occurred. Error reasons
+ are unique within a particular domain of errors. The error reason
+ **must** do the following:
+ * Be at most 63 characters and match a regular expression of
+ \`\[A-Z\]\[A-Z0-9\_\]+\[A-Z0-9\]\`, which represents
+ UPPER_SNAKE_CASE.
+ * Be unique and consumable by machine actors for automation.
+ * Be meaningful enough for a human reader to understand what the
+ reason refers to.
+ * Map to one and only one cause, That is, avoid making machine actors
+ reliant on ErrorInfo.
+ * *Example*: CPU_AVAILABILITY
+ * Distill your error message into its simplest form. For example, if
+ your error message is: `The Book, "The Great Gatsby", is unavailable
+ at the Library, "Garfield East". It is expected to be available
+ again on 2199-05-13.` The `reason string`could be one of the
+ following text examples in UPPER_SNAKE_CASE:
+ * UNAVAILABLE
+ * NO_STOCK
+ * CHECKED_OUT
+ * AVAILABILITY_ERROR
+ * In contrast, using any of the following reasons breaches the
+ intended formatting and is not recommended:
+ * noBooks
+ * THE_BOOK_YOU_WANT_IS_NOT_AVAILABLE
+ * ERROR
+ * librariesAreGreat
+* `domain string`
+ * The logical grouping to which the `reason` belongs. The error domain is
+ typically the registered service name of the tool or product that
+ generated the error. The domain must be a globally unique value.
+ * *Example*: \"`pubsub.googleapis.com`\".
+* `metadata map`
+ * Additional structured details about this error, which **should** provide
+ important context for customers to identify resolution steps. Keys
+ **should** match /\[a-zA-Z0-9-\_\]/ and be limited to 64 characters in
+ length. When identifying the current value of an exceeded limit, the
+ units **should** be contained in the key, not the value.
+ * *Example*: `"zone": "us-east1-a", "vmType": "e2-medium", "attachment":
+ "local-ssd=3,nvidia-t4=2"`
+ * For guidance on using the metadata map, see
+ [Dynamic Variables](#dynamic-variables).
##### Dynamic variables
-The best, actionable error messages include dynamic segments. These variable parts of the message are specific to a particular request. Without such context, it is unlikely that the message will be fully actionable by the user.
+The best, actionable error messages include dynamic segments. These variable
+parts of the message are specific to a particular request. Without such context,
+it is unlikely that the message will be fully actionable by the user.
-This practice is critical so that machine actors do not need to rely on `LocalizedMessage.message`, which is subject to change and is not part of the API contract.
+This practice is critical so that machine actors do not need to rely on
+`LocalizedMessage.message`, which is subject to change and is not part of the
+API contract.
Consider the following example:
@@ -156,9 +247,15 @@ Consider the following example:
It is expected to be available again on 2199-05-13.
```
-The preceding error message is made actionable by the context, both originating from the request, the title of the Book, the name of the Library, and by the information that is known only by the service, that is, the expected return date of the Book.
+The preceding error message is made actionable by the context, both originating
+from the request, the title of the Book, the name of the Library, and by the
+information that is known only by the service, that is, the expected return date
+of the Book.
-All dynamic variables found in error messages **must** also be present in the `map[google.rpc.LocalizedMessage](https://github.com/googleapis/googleapis/blob/e9897ed945336e2dc967b439ac7b4be6d2c62640/google/rpc/error_details.proto#L275-L285)
in Status.details
. The value of the Status.message string
should be presented in the service's native language in the LocalizedMessage.message
string, while also ensuring that the locale
string shows the correct language.
+If a localized error message is required, the service **must** include
+[google.rpc.LocalizedMessage](https://github.com/googleapis/googleapis/blob/e9897ed945336e2dc967b439ac7b4be6d2c62640/google/rpc/error_details.proto#L275-L285)
+in Status.details
. The value of the Status.message
+string
should be presented in the service's native
+language in the LocalizedMessage.message
string, while also
+ensuring that the locale
string shows the correct language.
##### LocalizedMessage payload
-The LocalizedMessage payload **should** contain the complete resolution to the error. If more information is needed than can fit in this payload, then additional resolution information **must** be provided in the HelpLink payload. See the [HelpLink payload](#helplink-payload) section for guidance.
+The LocalizedMessage payload **should** contain the complete resolution to the
+error. If more information is needed than can fit in this payload, then
+additional resolution information **must** be provided in the HelpLink payload.
+See the [HelpLink payload](#helplink-payload) section for guidance.
-For pre-existing (brownfield) APIs, the content in this `message` string will differ from the `message` string in `google.rpc.status`.
+For pre-existing (brownfield) APIs, the content in this `message` string will
+differ from the `message` string in `google.rpc.status`.
[LocalizedMessage Payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L277)
-Details of this object are summarized in the following ields, field descriptions, and examples:
-
-* `locale string`
- * The locale that follows the specification defined in [IETF bcp47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) (Tags for Identifying Languages).
- * *Example*: "en-US" , "fr-CH", "es-MX"
-* `message string`
- * The error message that the customer will receive through their chosen service, which **should** include a brief description of the error and a call to action to resolve the error. The message **should** include, where needed, data provided in other fields such as metadata.
- * Give users clear and concise instructions for resolving the error, which **must** be explicit as possible; for example:
- * `Consider trying your request in the [google.rpc.LocalizedMessage](https://github.com/googleapis/googleapis/blob/e9897ed945336e2dc967b439ac7b4be6d2c62640/google/rpc/error_details.proto#L275-L285)
to [Status.details](https://github.com/googleapis/googleapis/blob/aeae5ea2b01ece6c0cee046ae84b881cdc62b95d/google/rpc/status.proto#L46-L48)
. LocalizedMessage
is meant for displaying messages to end users.
-
-The error message presented in `LocalizedMessage.message` **should** be the same as `Status.message` or it **should** be an alternate message. Add as much information as the consumer of the error needs to resolve the error, but succinctly.
-
-Reasons to present the same error message in both locations include the following:
-
-* The service plans to localize either immediately or in the near future. See, "[Localization](https://google.aip.dev/193#localization)".
-* This practice enables clients to find an error message consistently in one location, `LocalizedMessaage.message`, across all methods of the API Service.
-
-Reasons to present an error message in `LocalizedMessage.message` that differs from `Status.message` include the following:
-
-* The service requires an end-user-facing error message that differs from the "debug message".
+By default, `LocalizedMessage` is populated with the same message as
+`Status.message`. Should you choose, you can also present a different
+`LocalizedMessage.message` from `Status.message`. The following are some reasons
+why.
+
+Keeping the aforementioned guidance in mind, the safest and recommended method
+to update an error message for a service is to add
+[google.rpc.LocalizedMessage](https://github.com/googleapis/googleapis/blob/e9897ed945336e2dc967b439ac7b4be6d2c62640/google/rpc/error_details.proto#L275-L285)
+to
+[Status.details](https://github.com/googleapis/googleapis/blob/aeae5ea2b01ece6c0cee046ae84b881cdc62b95d/google/rpc/status.proto#L46-L48)
.
+LocalizedMessage
is meant for displaying messages to end users.
+
+The error message presented in `LocalizedMessage.message` **should** be the same
+as `Status.message` or it **should** be an alternate message. Add as much
+information as the consumer of the error needs to resolve the error, but
+succinctly.
+
+Reasons to present the same error message in both locations include the
+following:
+
+* The service plans to localize either immediately or in the near future. See,
+ "[Localization](https://google.aip.dev/193#localization)".
+* This practice enables clients to find an error message consistently in one
+ location, `LocalizedMessaage.message`, across all methods of the API
+ Service.
+
+Reasons to present an error message in `LocalizedMessage.message` that differs
+from `Status.message` include the following:
+
+* The service requires an end-user-facing error message that differs from the
+ "debug message".
* Ongoing, iterative error message improvements are expected.
-When including `LocalizedMessage`, both `locale` and `message` **must** be populated. If the service is to be localized, the value of `locale` **must** change dynamically. See [Localization](https://google.aip.dev/193#localization). Otherwise, `locale` **must** always present the service's default locale; for example, "en-US".
+When including `LocalizedMessage`, both `locale` and `message` **must** be
+populated. If the service is to be localized, the value of `locale` **must**
+change dynamically. See [Localization](https://google.aip.dev/193#localization).
+Otherwise, `locale` **must** always present the service's default locale; for
+example, "en-US".
-When adding an error message using `LocalizedMessage`, `ErrorInfo` **must** be introduced either before or at the same time. If there are dynamic segments found in the text, the values of these variables **must** be included in `ErrorInfo.metadata`. See, "[Dynamic variables](#dynamic-variables)".
+When adding an error message using `LocalizedMessage`, `ErrorInfo` **must** be
+introduced either before or at the same time. If there are dynamic segments
+found in the text, the values of these variables **must** be included in
+`ErrorInfo.metadata`. See, "[Dynamic variables](#dynamic-variables)".
-**Warning:** If `LocalizedMessage` is released without `ErrorInfo`, the same [concerns](#status-message-warning) regarding client misuse of textual error messages apply.
+**Warning:** If `LocalizedMessage` is released without `ErrorInfo`, the same
+[concerns](#status-message-warning) regarding client misuse of textual error
+messages apply.
#### Message Layout
-Actionable error messages are consumed by human actors, often brokered by a specific surface. For these messages to be maximally useful and actionable, an effective layout is imperative.
+Actionable error messages are consumed by human actors, often brokered by a
+specific surface. For these messages to be maximally useful and actionable, an
+effective layout is imperative.
-The following layout guidelines make error messages easy to read or scan.
+The following layout guidelines make error messages easy to read or scan.
-The presentation depends on the product surface, so these guidelines explain best practices for a standard layout across common product surfaces such as gcloud, Pantheon, or Terraform.
+The presentation depends on the product surface, so these guidelines explain
+best practices for a standard layout across common product surfaces such as
+gcloud, Pantheon, or Terraform.
* Place the Error description in the first line (required)
* List each instance of metadata in a new line, indented
* Place the Resolution in a newline after a line space
* Include a hyperlink for documentation as part of the description
-The following example shows an actionable error message for the gcloud command line according to these guidelines.
+The following example shows an actionable error message for the gcloud command
+line according to these guidelines.
```
ERROR: 429 RESOURCE_EXHAUSTED
@@ -304,58 +471,88 @@ https://cloud.google.com/compute/docs/resource-error
### Partial errors
-APIs **should not** support partial errors. Partial errors add significant complexity for users, because they usually sidestep the use of error codes, or move those error codes into the response message, where the user **must** write specialized error handling logic to address the problem.
+APIs **should not** support partial errors. Partial errors add significant
+complexity for users, because they usually sidestep the use of error codes, or
+move those error codes into the response message, where the user **must** write
+specialized error handling logic to address the problem.
-However, occasionally partial errors are necessary, particularly in bulk operations where it would be hostile to users to fail an entire large request because of a problem with a single entry.
+However, occasionally partial errors are necessary, particularly in bulk
+operations where it would be hostile to users to fail an entire large request
+because of a problem with a single entry.
-Methods that require partial errors **should** use [long-running operations](https://google.aip.dev/151), and the method **should** put partial failure information in the metadata message. The errors themselves **must** still be represented with a [google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
object.
+Methods that require partial errors **should** use
+[long-running operations](https://google.aip.dev/151), and the method **should**
+put partial failure information in the metadata message. The errors themselves
+**must** still be represented with a
+[google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
+object.
### Permission Denied
-If the user does not have permission to access the resource or parent, regardless of whether or not it exists, the service **must** error with `PERMISSION_DENIED` (HTTP 403). Permission **must** be checked prior to checking if the resource or parent exists.
+If the user does not have permission to access the resource or parent,
+regardless of whether or not it exists, the service **must** error with
+`PERMISSION_DENIED` (HTTP 403). Permission **must** be checked prior to checking
+if the resource or parent exists.
-If the user does have proper permission, but the requested resource or parent does not exist, the service **must** error with `NOT_FOUND` (HTTP 404).
+If the user does have proper permission, but the requested resource or parent
+does not exist, the service **must** error with `NOT_FOUND` (HTTP 404).
## Rationale
### Requiring ErrorInfo
-`ErrorInfo` is required because it further identifies an error. With only approximately twenty [available values](https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto) for `Status.status`, it is difficult to disambiguate one error from another across an entire [API Service](https://cloud.google.com/apis/design/glossary#api_service).
+`ErrorInfo` is required because it further identifies an error. With only
+approximately twenty
+[available values](https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto)
+for `Status.status`, it is difficult to disambiguate one error from another
+across an entire
+[API Service](https://cloud.google.com/apis/design/glossary#api_service).
-Also, error messages often contain dynamic segments that express variable information, so there needs to be machine-readable component of _every_ error response that enables clients to use such information programmatically.
+Also, error messages often contain dynamic segments that express variable
+information, so there needs to be machine-readable component of *every* error
+response that enables clients to use such information programmatically.
### LocalizedMessage
-`LocalizedMessage` was selected as the location to present alternate error messages. This is desirable when clients need to display a crafted error message directly to end users. `LocalizedMessage` can be used with a static `locale`. This may seem misleading, but it allows the service to eventually localize without having to duplicate or move the error message, which would be a backwards incompatible change.
+`LocalizedMessage` was selected as the location to present alternate error
+messages. This is desirable when clients need to display a crafted error message
+directly to end users. `LocalizedMessage` can be used with a static `locale`.
+This may seem misleading, but it allows the service to eventually localize
+without having to duplicate or move the error message, which would be a
+backwards incompatible change.
### Updating Status.Message
-**Because Status.Message is part of the API contract**, avoid updating it entirely in favor of updating LocalizedMessage; for example, clients often perform string matches on the text to differentiate one error for another and even parse the error message to extract variables from dynamic segments.
+**Because Status.Message is part of the API contract**, avoid updating it
+entirely in favor of updating LocalizedMessage; for example, clients often
+perform string matches on the text to differentiate one error for another and
+even parse the error message to extract variables from dynamic segments.
## Further reading
* For which error codes to retry, see [AIP-194](https://aip.dev/194).
-* For how to retry errors in client libraries, see [AIP-4221](https://aip.dev/client-libraries/4221).
+* For how to retry errors in client libraries, see
+ [AIP-4221](https://aip.dev/client-libraries/4221).
## Changelog
-- **2024-01-10**: Incorporate guidance for writing effective messages.
-- **2023-05-17**: Change the recommended language for `Status.message`
- to be the service's native language rather than English.
-- **2023-05-17**: Specify requirements for changing error messages.
-- **2023-05-10**: Require [`ErrorInfo`][ErrorInfo] for all error
- responses.
-- **2023-05-04**: Require uniqueness by message type for error details.
-- **2022-11-04**: Added guidance around PERMISSION_DENIED errors previously
- found in other AIPs.
-- **2022-08-12**: Reworded/Simplified intro to add clarity to the intent.
-- **2020-01-22**: Added a reference to the [`ErrorInfo`][ErrorInfo] message.
-- **2019-10-14**: Added guidance restricting error message mutability to if
- there is a machine-readable identifier present.
-- **2019-09-23**: Added guidance about error message strings being able to
- change.
+- **2024-01-10**: Incorporate guidance for writing effective messages.
+- **2023-05-17**: Change the recommended language for `Status.message` to be
+ the service's native language rather than English.
+- **2023-05-17**: Specify requirements for changing error messages.
+- **2023-05-10**: Require [`ErrorInfo`][ErrorInfo] for all error responses.
+- **2023-05-04**: Require uniqueness by message type for error details.
+- **2022-11-04**: Added guidance around PERMISSION_DENIED errors previously
+ found in other AIPs.
+- **2022-08-12**: Reworded/Simplified intro to add clarity to the intent.
+- **2020-01-22**: Added a reference to the [`ErrorInfo`][ErrorInfo] message.
+- **2019-10-14**: Added guidance restricting error message mutability to if
+ there is a machine-readable identifier present.
+- **2019-09-23**: Added guidance about error message strings being able to
+ change.
+
[aip-4221]: ../client-libraries/4221.md
[details]: https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto
[ErrorInfo]: https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L27-L76
@@ -368,4 +565,5 @@ Also, error messages often contain dynamic segments that express variable inform
[Status details]: https://github.com/googleapis/googleapis/blob/aeae5ea2b01ece6c0cee046ae84b881cdc62b95d/google/rpc/status.proto#L46-L48
[long-running operations]: ./0151.md
[API Service]: https://cloud.google.com/apis/design/glossary#api_service
-
+
+
\ No newline at end of file
From cdf76cdc657e4bcd7d390e08fa9a1ed6d14afdfd Mon Sep 17 00:00:00 2001
From: jschneider11 <38144056+jschneider11@users.noreply.github.com>
Date: Sat, 3 Feb 2024 00:23:14 +0000
Subject: [PATCH 09/11] Fixed indentation problem starting at line 207.
---
aip/general/0193.md | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/aip/general/0193.md b/aip/general/0193.md
index 0884b7e1c..32e75370e 100644
--- a/aip/general/0193.md
+++ b/aip/general/0193.md
@@ -204,16 +204,17 @@ descriptions, and examples:
at the Library, "Garfield East". It is expected to be available
again on 2199-05-13.` The `reason string`could be one of the
following text examples in UPPER_SNAKE_CASE:
- * UNAVAILABLE
- * NO_STOCK
- * CHECKED_OUT
- * AVAILABILITY_ERROR
- * In contrast, using any of the following reasons breaches the
- intended formatting and is not recommended:
- * noBooks
- * THE_BOOK_YOU_WANT_IS_NOT_AVAILABLE
- * ERROR
- * librariesAreGreat
+ * UNAVAILABLE
+ * NO_STOCK
+ * CHECKED_OUT
+ * AVAILABILITY_ERROR
+ * In contrast, using any of the following
+ reasons breaches the
+ intended formatting and is not recommended:
+ * noBooks
+ * THE_BOOK_YOU_WANT_IS_NOT_AVAILABLE
+ * ERROR
+ * librariesAreGreat
* `domain string`
* The logical grouping to which the `reason` belongs. The error domain is
typically the registered service name of the tool or product that
From 6e0f6203ae431621987c33bc886e38379ff792a9 Mon Sep 17 00:00:00 2001
From: jschneider11 <38144056+jschneider11@users.noreply.github.com>
Date: Mon, 5 Feb 2024 14:20:27 -0800
Subject: [PATCH 10/11] Update 0193.md
Adding writing guidance and converting HTML to Markdown.
---
aip/general/0193.md | 291 +++++++++++++++++++++++---------------------
1 file changed, 155 insertions(+), 136 deletions(-)
diff --git a/aip/general/0193.md b/aip/general/0193.md
index 32e75370e..e2fe23397 100644
--- a/aip/general/0193.md
+++ b/aip/general/0193.md
@@ -17,10 +17,10 @@ error handling code.
## Guidance
Services **must** return a
-[google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
-message when an API error occurs, and must use the canonical
+[`google.rpc.Status`](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
+message when an API error occurs, and **must** use the canonical
error codes defined in
-[google.rpc.Code](https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto)
.
+[`google.rpc.Code`](https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto).
More information about the particular codes is available in the
[gRPC status code documentation](https://github.com/grpc/grpc/blob/master/doc/statuscodes.md).
@@ -36,8 +36,10 @@ or ask questions to help resolve the issue. It is also important to
[set the right tone](https://developers.google.com/tech-writing/error-messages/set-tone)
when writing messages.
+
### Error Response
+
#### JSON representation
A JSON representation of an error response might look like the following
@@ -47,56 +49,57 @@ For the purposes of following best practices, it’s helpful to break the error
response into sections. Note that the order in which you write the error message
is often different from how the error is presented to users.
+
```json
{
- "error": {
- "code": 429,
- "message": "The zone 'us-east1-a' does not have enough resources available to fulfill the request. Try a different zone, or try again later.",
- "status": "RESOURCE_EXHAUSTED",
- "details": [
- {
- "@type": "type.googleapis.com/google.rpc.ErrorInfo",
- "reason": "RESOURCE_AVAILABILITY",
- "domain": "compute.googleapis.com",
- "metadata": {
- "zone": "us-east1-a",
- "vmType": "e2-medium",
- "attachment": "local-ssd=3,nvidia-t4=2",
- "zonesWithCapacity": "us-central1-f,us-central1-c"
- }
- },
- {
- "@type": "type.googleapis.com/google.rpc.LocalizedMessage",
- "locale": "en-US",
- "message": "An [google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
-as follows:
+[`google.rpc.Status`](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto) as follows:
* present a developer-facing, human-readable "debug message"
* present the message in the service's native language
* explain both the error and offer an actionable resolution to it
- ([citation](https://cloud.google.com/apis/design/errors#error_model))
+ ([citation](https://cloud.google.com/apis/design/errors#error_model))
**Note:** Sometimes a service will elect to always present `Status.message` in
English rather than the application's native language so that messages are
@@ -105,38 +108,41 @@ easily searchable in common knowledge bases, such as StackOverflow™.
Important points:
* This `message` string is considered a problem description. It is intended
- for human developers to understand the problem and is more detailed than
- [ErrorInfo.reason](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L57)
,
- discussed in the next section.
+ for human developers to understand the problem and is more detailed than
+ [`ErrorInfo.reason`](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L57),
+ discussed in the next section.
* Use simple descriptive language that is easy to understand (without
- technical jargon) to clearly state the problem that results in an error.
+ technical jargon) to clearly state the problem that results in an error.
* For pre-existing (brownfield) APIs, the information in
- google.rpc.Status
already exists and can’t be changed. In this
- case, do not edit anything in this google.rpc.Status
, because
- some users might have automation running against the pre-existing content.
- For example, any changes in text for the message
string could
- cause breakages. For more information, see
- [Changing Error Messages](#changing-error-messages).
+ `google.rpc.Status` already exists and can’t be changed. In this
+ case, do not edit anything in this `google.rpc.Status`, because
+ some users might have automation running against the pre-existing content.
+ For example, any changes in text for the `message` string could
+ cause breakages. For more information, see
+ [Changing Error Messages](#changing-error-messages).
+
##### [google.rpc.Status payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
Details of this object are summarized in the following fields, field
descriptions, and examples:
-* `code int32`
- * The status code, which **should** be an enum value of
- [google.rpc.Code](https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto).
- * *Example*: 429
+
+* `code int32`
+ * The status code, which **should** be an enum value of
+ [`google.rpc.Code`](https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto).
+ * *Example*: 429
* `message string`
- * A developer-facing error message, which **should** be in English. Any
- user-facing error message **should** be located in the LocalizedMessage
- payload.
- * *Example message*: \"The zone \'us-east1-a\' does not have enough
- resources available to fulfill the request. Try a different zone, or try
- again later.\"
+ * A developer-facing error message, which **should** be in English. Any
+ user-facing error message **should** be located in the LocalizedMessage
+ payload.
+ * *Example message*: \"The zone \'us-east1-a\' does not have enough
+ resources available to fulfill the request. Try a different zone, or try
+ again later.\"
* `details Object (repeated)`
- * Text
- * *Example*: Described in the [ErrorDetails](#error-details) section.
+ * Text
+ * *Example*: Described in the [ErrorDetails](#error-details) section.
+
#### [ErrorDetails](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto)
@@ -154,23 +160,24 @@ error message **must** be considered a backwards-incompatible change.
For the purpose of this discussion, the ErrorDetails section contains three
payloads: `ErrorInfo`, `LocalizedMessage`, and `HelpLink`.
+
##### Uniqueness
Each type of detail payload **must** be included at most once. For example,
there **must not** be more than one
-[BadRequest](https://github.com/googleapis/googleapis/blob/477a59d764428136ba1d857a9633c0d231de6efa/google/rpc/error_details.proto#L168-L218)
-message in the details
, but there may be a
-BadRequest
and a
-[PreconditionFailure](https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L139-L166)
.
+[`BadRequest`](https://github.com/googleapis/googleapis/blob/477a59d764428136ba1d857a9633c0d231de6efa/google/rpc/error_details.proto#L168-L218)
+message in the `details`, but there **may** be a
+`BadRequest` and a
+[`PreconditionFailure`](https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L139-L166).
+
##### ErrorInfo payload
-The
-[ErrorInfo](https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L27-L76)
+The [`ErrorInfo`](https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L27-L76)
message is the required way to send a machine-readable identifier. All error
-responses must include an ErrorInfo
payload in
-details
. Variable information should be included
-in metadata
in ErrorInfo
and must be
+responses **must** include an `ErrorInfo` payload in
+`details`. Variable information **should** be included
+in `metadata` in `ErrorInfo` and **must** be
included if it appears within an error message.
When introducing an error that represents a failure scenario that did not
@@ -186,50 +193,51 @@ in `ErrorInfo.metadata` (See [Dynamic variables](#dynamic-variables).
Details of this object are summarized in the following fields, field
descriptions, and examples:
-* `reason string`
- * A short snake_case description of why the error occurred. Error reasons
- are unique within a particular domain of errors. The error reason
- **must** do the following:
- * Be at most 63 characters and match a regular expression of
- \`\[A-Z\]\[A-Z0-9\_\]+\[A-Z0-9\]\`, which represents
- UPPER_SNAKE_CASE.
- * Be unique and consumable by machine actors for automation.
- * Be meaningful enough for a human reader to understand what the
- reason refers to.
- * Map to one and only one cause, That is, avoid making machine actors
- reliant on ErrorInfo.
- * *Example*: CPU_AVAILABILITY
- * Distill your error message into its simplest form. For example, if
- your error message is: `The Book, "The Great Gatsby", is unavailable
- at the Library, "Garfield East". It is expected to be available
- again on 2199-05-13.` The `reason string`could be one of the
- following text examples in UPPER_SNAKE_CASE:
- * UNAVAILABLE
- * NO_STOCK
- * CHECKED_OUT
- * AVAILABILITY_ERROR
- * In contrast, using any of the following
- reasons breaches the
- intended formatting and is not recommended:
- * noBooks
- * THE_BOOK_YOU_WANT_IS_NOT_AVAILABLE
- * ERROR
- * librariesAreGreat
-* `domain string`
- * The logical grouping to which the `reason` belongs. The error domain is
- typically the registered service name of the tool or product that
- generated the error. The domain must be a globally unique value.
- * *Example*: \"`pubsub.googleapis.com`\".
-* `metadata map`
- * Additional structured details about this error, which **should** provide
- important context for customers to identify resolution steps. Keys
- **should** match /\[a-zA-Z0-9-\_\]/ and be limited to 64 characters in
- length. When identifying the current value of an exceeded limit, the
- units **should** be contained in the key, not the value.
- * *Example*: `"zone": "us-east1-a", "vmType": "e2-medium", "attachment":
- "local-ssd=3,nvidia-t4=2"`
- * For guidance on using the metadata map, see
- [Dynamic Variables](#dynamic-variables).
+* `reason string`
+ * A short snake_case description of why the error occurred. Error reasons
+ are unique within a particular domain of errors. The error reason
+ **must** do the following:
+ * Be at most 63 characters and match a regular expression of
+ \`\[A-Z\]\[A-Z0-9\_\]+\[A-Z0-9\]\`, which represents
+ UPPER_SNAKE_CASE.
+ * Be unique and consumable by machine actors for automation.
+ * Be meaningful enough for a human reader to understand what the
+ reason refers to.
+ * Map to one and only one cause, That is, avoid making machine actors
+ reliant on ErrorInfo.
+ * *Example*: CPU_AVAILABILITY
+ * Distill your error message into its simplest form. For example, if
+ your error message is: `The Book, "The Great Gatsby", is unavailable
+ at the Library, "Garfield East". It is expected to be available
+ again on 2199-05-13.` The `reason string`could be one of the
+ following text examples in UPPER_SNAKE_CASE:
+ * UNAVAILABLE
+ * NO_STOCK
+ * CHECKED_OUT
+ * AVAILABILITY_ERROR
+ * In contrast, using any of the following
+ reasons breaches the
+ intended formatting and is not recommended:
+ * noBooks
+ * THE_BOOK_YOU_WANT_IS_NOT_AVAILABLE
+ * ERROR
+ * librariesAreGreat
+* `domain string`
+ * The logical grouping to which the `reason` belongs. The error domain is
+ typically the registered service name of the tool or product that
+ generated the error. The domain must be a globally unique value.
+ * *Example*: \"`pubsub.googleapis.com`\".
+* `metadata map`
+ * Additional structured details about this error, which **should** provide
+ important context for customers to identify resolution steps. Keys
+ **should** match /\[a-zA-Z0-9-\_\]/ and be limited to 64 characters in
+ length. When identifying the current value of an exceeded limit, the
+ units **should** be contained in the key, not the value.
+ * *Example*: `"zone": "us-east1-a", "vmType": "e2-medium", "attachment":
+ "local-ssd=3,nvidia-t4=2"`
+ * For guidance on using the metadata map, see
+ [Dynamic Variables](#dynamic-variables).
+
##### Dynamic variables
@@ -244,8 +252,8 @@ API contract.
Consider the following example:
```
- The Book, "The Great Gatsby", is unavailable at the Library, "Garfield East".
- It is expected to be available again on 2199-05-13.
+ The Book, "The Great Gatsby", is unavailable at the Library, "Garfield East".
+ It is expected to be available again on 2199-05-13.
```
The preceding error message is made actionable by the context, both originating
@@ -284,11 +292,11 @@ key is empty. Keys **must** be expressed as lower camel-case.
##### Localization
If a localized error message is required, the service **must** include
-[google.rpc.LocalizedMessage](https://github.com/googleapis/googleapis/blob/e9897ed945336e2dc967b439ac7b4be6d2c62640/google/rpc/error_details.proto#L275-L285)
-in Status.details
. The value of the Status.message
-string
should be presented in the service's native
-language in the LocalizedMessage.message
string, while also
-ensuring that the locale
string shows the correct language.
+[`google.rpc.LocalizedMessage`](https://github.com/googleapis/googleapis/blob/e9897ed945336e2dc967b439ac7b4be6d2c62640/google/rpc/error_details.proto#L275-L285)
+in `Status.details`. The value of the `Status.message`
+string **should** be presented in the service's native
+language in the `LocalizedMessage.message` string, while also
+ensuring that the `locale` string shows the correct language.
##### LocalizedMessage payload
@@ -302,7 +310,7 @@ differ from the `message` string in `google.rpc.status`.
[LocalizedMessage Payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L277)
-Details of this object are summarized in the following ields, field
+Details of this object are summarized in the following fields, field
descriptions, and examples:
* `locale string`
@@ -319,7 +327,7 @@ descriptions, and examples:
**must** be explicit as possible; for example:
* `Consider trying your request in the [google.rpc.LocalizedMessage](https://github.com/googleapis/googleapis/blob/e9897ed945336e2dc967b439ac7b4be6d2c62640/google/rpc/error_details.proto#L275-L285)
+[`google.rpc.LocalizedMessage`](https://github.com/googleapis/googleapis/blob/e9897ed945336e2dc967b439ac7b4be6d2c62640/google/rpc/error_details.proto#L275-L285)
to
-[Status.details](https://github.com/googleapis/googleapis/blob/aeae5ea2b01ece6c0cee046ae84b881cdc62b95d/google/rpc/status.proto#L46-L48)
.
-LocalizedMessage
is meant for displaying messages to end users.
+[`Status.details`](https://github.com/googleapis/googleapis/blob/aeae5ea2b01ece6c0cee046ae84b881cdc62b95d/google/rpc/status.proto#L46-L48).
+`LocalizedMessage` is meant for displaying messages to end users.
The error message presented in `LocalizedMessage.message` **should** be the same
as `Status.message` or it **should** be an alternate message. Add as much
@@ -404,21 +415,21 @@ Reasons to present the same error message in both locations include the
following:
* The service plans to localize either immediately or in the near future. See,
- "[Localization](https://google.aip.dev/193#localization)".
+ "[Localization](https://google.aip.dev/193#localization)".
* This practice enables clients to find an error message consistently in one
- location, `LocalizedMessaage.message`, across all methods of the API
- Service.
+ location, `LocalizedMessaage.message`, across all methods of the API
+ Service.
Reasons to present an error message in `LocalizedMessage.message` that differs
from `Status.message` include the following:
* The service requires an end-user-facing error message that differs from the
- "debug message".
+ "debug message".
* Ongoing, iterative error message improvements are expected.
When including `LocalizedMessage`, both `locale` and `message` **must** be
populated. If the service is to be localized, the value of `locale` **must**
-change dynamically. See [Localization](https://google.aip.dev/193#localization).
+change dynamically. See "[Localization](https://google.aip.dev/193#localization)".
Otherwise, `locale` **must** always present the service's default locale; for
example, "en-US".
@@ -470,6 +481,7 @@ the troubleshooting documentation:
https://cloud.google.com/compute/docs/resource-error
```
+
### Partial errors
APIs **should not** support partial errors. Partial errors add significant
@@ -485,9 +497,10 @@ Methods that require partial errors **should** use
[long-running operations](https://google.aip.dev/151), and the method **should**
put partial failure information in the metadata message. The errors themselves
**must** still be represented with a
-[google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
+[`google.rpc.Status`](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto)
object.
+
### Permission Denied
If the user does not have permission to access the resource or parent,
@@ -498,8 +511,10 @@ if the resource or parent exists.
If the user does have proper permission, but the requested resource or parent
does not exist, the service **must** error with `NOT_FOUND` (HTTP 404).
+
## Rationale
+
### Requiring ErrorInfo
`ErrorInfo` is required because it further identifies an error. With only
@@ -513,6 +528,7 @@ Also, error messages often contain dynamic segments that express variable
information, so there needs to be machine-readable component of *every* error
response that enables clients to use such information programmatically.
+
### LocalizedMessage
`LocalizedMessage` was selected as the location to present alternate error
@@ -522,6 +538,7 @@ This may seem misleading, but it allows the service to eventually localize
without having to duplicate or move the error message, which would be a
backwards incompatible change.
+
### Updating Status.Message
**Because Status.Message is part of the API contract**, avoid updating it
@@ -529,11 +546,13 @@ entirely in favor of updating LocalizedMessage; for example, clients often
perform string matches on the text to differentiate one error for another and
even parse the error message to extract variables from dynamic segments.
+
## Further reading
* For which error codes to retry, see [AIP-194](https://aip.dev/194).
* For how to retry errors in client libraries, see
- [AIP-4221](https://aip.dev/client-libraries/4221).
+ [AIP-4221](https://aip.dev/client-libraries/4221).
+
## Changelog
@@ -567,4 +586,4 @@ even parse the error message to extract variables from dynamic segments.
[long-running operations]: ./0151.md
[API Service]: https://cloud.google.com/apis/design/glossary#api_service
-
\ No newline at end of file
+
From e5be3937233a3f013ff9a59c3a8de495741b6ca2 Mon Sep 17 00:00:00 2001
From: Sam Woodard