From ef58f403c2cb928a15f6beee93991546ba443c4d Mon Sep 17 00:00:00 2001 From: jschneider11 <38144056+jschneider11@users.noreply.github.com> Date: Tue, 16 Jan 2024 19:03:18 -0800 Subject: [PATCH 01/11] Update 0193.md Incorporating writing guidance for messages into AIP-193. --- aip/general/0193.md | 515 ++++++++++++++++++++++++++++++-------------- 1 file changed, 350 insertions(+), 165 deletions(-) diff --git a/aip/general/0193.md b/aip/general/0193.md index d8ec5a7ad..994456ffc 100644 --- a/aip/general/0193.md +++ b/aip/general/0193.md @@ -6,48 +6,39 @@ placement: category: polish order: 30 --- - # Errors -Effective error communication is an important part of designing simple and -intuitive APIs. Services returning standardized error responses enable API -clients to construct centralized common error handling logic. This common logic -simplifies API client applications and eliminates the need for cumbersome -custom error handling code. +Effective error communication is an important part of designing simple and intuitive APIs. Services returning standardized error responses enable API clients to construct centralized common error handling logic. This common logic simplifies API client applications and eliminates the need for cumbersome custom error handling code. ## Guidance -Services **must** return a [`google.rpc.Status`][Status] message when an API -error occurs, and **must** use the canonical error codes defined in -[`google.rpc.Code`][Code]. More information about the particular codes is -available in the [gRPC status code documentation][]. +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** 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 +``` +<<<<<>>>>> { "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.", + "message": "The zone 'us-east1-a' does not have enough resources available to fulfill the request. Try a different zone, or try again later.", <<>>>>> +<<<<<>>>>> { "@type": "type.googleapis.com/google.rpc.ErrorInfo", - "reason": "RESOURCE_AVAILABILITY", + "reason": "RESOURCE_AVAILABILITY", <<< ErrorInfo reason "domain": "compute.googleapis.com", "metadata": { "zone": "us-east1-a", @@ -56,16 +47,22 @@ following: "zonesWithCapacity": "us-central1-f,us-central1-c" } }, +<<<<<>>>>> { "@type": "type.googleapis.com/google.rpc.LocalizedMessage", "locale": "en-US", - "message": "An VM instance with is currently unavailable in the zone.\n Consider trying your request in the zone(s), which currently has/have capacity to accommodate your request.\n Alternatively, you can try your request again with a different VM hardware configuration or at a later time. For more information, see the troubleshooting documentation." + "message": "An VM instance with is currently unavailable in the zone. + Consider trying your request in the zone(s), which currently has/have capacity + to accommodate your request. + Alternatively, you can try your request again with a different VM hardware configuration or at a later time. + For more information, see the troubleshooting documentation."<<>>>>> { "@type": "type.googleapis.com/google.rpc.Help", "links": [ { - "description": "troubleshooting documentation", + "description": "Additional information on this error", "url": "https://cloud.google.com/compute/docs/resource-error" } ] @@ -75,205 +72,393 @@ following: } ``` -### Details +#### 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: + +* 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. +

+ +
+ +#### [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. + +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`. + +##### 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). + +##### 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:

    + +
  • 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 + +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. + +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 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`, `ErrorInfo.metadata` (found on the _required_ `ErrorInfo`). For example, the `metadata` map for the sample error message above will include _at least_ the following key/value pairs: + +``` +bookTitle: "The Great Gatsby" +library: "Garfield East" +expectedReturnDate: "2199-05-13" +``` + +The following example shows an additional example of a metadata map for information about virtual machines: -Google defines a set of [standard detail payloads][details] for error details, -which cover most common needs for API errors. Services **should** use these -standard details payloads when feasible. +``` +vmType: "", +attachment: "" +zone: "" +``` -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` field, changing the -error message **must** be considered a backwards-incompatible change. +Dynamic variables that do not appear in an error message **may** also be included in `metadata` to provide additional information to the client to be used programmatically. -#### ErrorInfo +Once present in `metadata`, keys **must** continue to be included in the map for the error payload to be backwards compatible, even if the value for a particular key is empty. Keys **must** be expressed as lower camel-case. -The [`ErrorInfo`][ErrorInfo] message is the required way to send a -machine-readable identifier. All error responses **must** include an -`ErrorInfo` payload in the `details` field. Variable information -**should** be included in the `metadata` field on `ErrorInfo` and -**must** be included if it appears within an error message. +##### Localization -#### Uniqueness +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. -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, + Consider trying your request in the <AVAILABLE-ZONE-1>, <AVAILABLE-ZONE-N> zone(s), which currently has/have capacity to accommodate your request. +

-- 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)) + Alternatively, you can try your request again with a different VM hardware configuration or at a later time. +

+If the error resolution exceeds the number of characters supported in the problem description +(message string of google.rpc.Status), or requires multiple troubleshooting +steps, include the most common resolution in the message and use the HelpLink payload to link to relevant documentation. +

-**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™. +##### HelpLink payload -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 `LocalizedMessage.message` doesn’t provide the user sufficient context or actionable next steps, or if there are multiple points of failure that need to be considered in troubleshooting, a link to supplemental troubleshooting documentation **must** be provided in the `HelpLink `payload. + +Provide this information in addition to a clear problem definition and actionable resolution, not as an alternative to them; for example. + +``` + For more information, see the troubleshooting documentation: https://cloud.google.com/compute/docs/resource-error. +``` + +[HelpLink payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L256) + + + + + + + + + + + + + + + +
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 +

+ +### Error messages + +The following sections describe best practices for error messages not described previously. #### Changing error messages - +##### Method -`Status.message` **may** change. However, **use extreme caution** when -doing so. API consumers often treat this error message as **part of the -API contract**. Clients perform string matches on the text to -differentiate one error for another and even parse the error message to -extract variables from dynamic segments. +The method of changing error messages depends on whether an ErrorInfo payload is present in the message. -There is a safer alternative. The service can chose to include an error -message by adding [`google.rpc.LocalizedMessage`][LocalizedMessage] to -[`Status.details`][Status details]. +If the error message contains ErrorInfo payload (a machine-readable identifier): -The error message presented in `LocalizedMessage.message` **may** be the -same as `Status.message` or it **may** be an alternate message. +* `Status.message` _string_ and `LocalizedMessage.message` _string_ can change +* New metadata fields can be added +* However, existing metadata fields **must not** be removed and existing metadata field keys cannot be modified. -Reasons to present the same error message in both locations include the -following: +If the error message does _not_ contain ErrorInfo payload (usually for pre-existing APIs): -- The service plans to localize either immediately or in the near - future. See, "[Localization](#localization)". -- It affords clients the ability to find an error message consistently - in one location, `LocalizedMessaage.message`, across all methods of - the API Service. +* The `LocalizedMessage.message` _string_ can change +* However, the `Status.message` _string_ **must** not be changed, as this change is backward-incompatible. -Reasons to present an error message in `LocalizedMessage.message` that -differs from `Status.message` include the following: +##### Message alignment -- The service requires an end-user facing error message that differs - from the "debug message". -- Ongoing, iterative error message improvements are expected. +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. -When including `LocalizedMessage`, both fields, `locale` and `message`, -**must** be populated. If the service is to be localized, the value of -`locale` **must** change dynamically. See, -"[Localization](#localization)". Otherwise, `locale` **must** always -present the service's default locale, e.g. "en-US". +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. -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`, `ErrorInfo.metadata` (found on the -*required* `ErrorInfo`). For example, the `metadata` map for the sample -error message above will include *at least* the following key/value -pairs: +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. + +#### 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. + +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. + +* 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. -```yaml -bookTitle: "The Great Gatsby" -library: "Garfield East" -expectedReturnDate: "2199-05-13" ``` +ERROR: 429 RESOURCE_EXHAUSTED -Dynamic variables that do not appear in an error message **may** also be -included in `metadata` to provide additional information to the client -to be used programmatically. +An n2d-standard-224 VM instance with 24 local SSD(s) is currently +unavailable in the us-central-1a zone. -Once present in `metadata`, keys **must** continue to be included in the -map for the error payload to be backwards compatible, even if the value -for a particular key is empty. Keys **must** be expressed as lower -camel-case. +"vm-type": "n2d-standard-224" +"attachment": "24 local SSD(s)" +"zone": "us-central-1a", -#### Localization +Consider trying your request in the us-central1-f, us-central1-c +zone(s), which currently has/have capacity to accommodate your request. -The value of `Status.message` **should** be presented in the service's -native language. If a localized error message is required, the service -**must** include [`google.rpc.LocalizedMessage`][LocalizedMessage] in -`Status.details`. +Alternatively, you can try your request again with a different VM +hardware configuration or at a later time. For more information, see +the troubleshooting documentation: +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][], -and the method **should** put partial failure information in the metadata -message. The errors themselves **must** still be represented with a -[`google.rpc.Status`][Status] 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][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. -

- -
+[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](ht | +| | tps://github.com/googleapis/googleapi | +| | s/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) @@ -153,73 +145,102 @@ 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) ++---------------------------------------+---------------------------------------+ +| **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). | ++---------------------------------------+---------------------------------------+ - - - - - - - - - - - - - - - - - -
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 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 @@ -268,41 +289,51 @@ 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 (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 <AVAILABLE-ZONE-1>, <AVAILABLE-ZONE-N> zone(s), which currently has/have capacity to accommodate your request. -

- - Alternatively, you can try your request again with a different VM hardware configuration or at a later time. -

-If the error resolution exceeds the number of characters supported in the problem description -(message string of google.rpc.Status), or requires multiple troubleshooting -steps, include the most common resolution in the message and use the HelpLink payload to link to relevant documentation. -

++---------------------------------------+---------------------------------------+ +| **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 | +| | , zone(s), which currently has/have c | +| | apacity to accommodate your request.` | +| | | +| | `Alternatively, you can try your req | +| | uest again with a different VM hardwa | +| | re configuration or at a later time.` | +| | | +| | If the error resolution exceeds the | +| | number of characters supported in the | +| | problem description (`message` string | +| | of `google.rpc.Status`), or requires | +| | multiple troubleshooting steps, | +| | include the most common resolution in | +| | the message and use the `HelpLink` | +| | payload to link to relevant | +| | documentation. | ++---------------------------------------+---------------------------------------+ + ##### HelpLink payload @@ -316,31 +347,23 @@ Provide this information in addition to a clear problem definition and actionabl [HelpLink payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L256) - - - - - - - - - - - - - - -
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 -

++---------------------------------------+---------------------------------------+ +| **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 | ++---------------------------------------+---------------------------------------+ ### Error messages From 946748110f700cbf1a8a9deb9bee01807bb07f9d Mon Sep 17 00:00:00 2001 From: jschneider11 <38144056+jschneider11@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:22:57 +0000 Subject: [PATCH 03/11] Correcting Markdown on the first table only. --- aip/general/0193.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aip/general/0193.md b/aip/general/0193.md index db168f0c9..d7dc0e340 100644 --- a/aip/general/0193.md +++ b/aip/general/0193.md @@ -92,9 +92,9 @@ Important points: [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](ht | @@ -102,7 +102,7 @@ Important points: | | s/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** | @@ -114,13 +114,13 @@ Important points: | | 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) From 48f5db81465cec62929ddfccdd5d6711525a4b4b Mon Sep 17 00:00:00 2001 From: jschneider11 <38144056+jschneider11@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:25:28 +0000 Subject: [PATCH 04/11] Removing pluses in first table for testing. --- aip/general/0193.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aip/general/0193.md b/aip/general/0193.md index d7dc0e340..0e0fa6625 100644 --- a/aip/general/0193.md +++ b/aip/general/0193.md @@ -92,9 +92,9 @@ Important points: [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](ht | @@ -102,7 +102,7 @@ Important points: | | s/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** | @@ -114,13 +114,13 @@ Important points: | | 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) From 552ed97315d267e52b0b625f13b7522924312b43 Mon Sep 17 00:00:00 2001 From: jschneider11 <38144056+jschneider11@users.noreply.github.com> Date: Mon, 22 Jan 2024 21:22:57 +0000 Subject: [PATCH 05/11] Updated JSON. Changed first table to bulleted list. --- aip/general/0193.md | 54 +++++++++++++-------------------------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/aip/general/0193.md b/aip/general/0193.md index 0e0fa6625..0467ce154 100644 --- a/aip/general/0193.md +++ b/aip/general/0193.md @@ -26,19 +26,16 @@ 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 { "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.", <<>>>>> -<<<<<>>>>> { "@type": "type.googleapis.com/google.rpc.ErrorInfo", - "reason": "RESOURCE_AVAILABILITY", <<< ErrorInfo reason + "reason": "RESOURCE_AVAILABILITY", "domain": "compute.googleapis.com", "metadata": { "zone": "us-east1-a", @@ -47,7 +44,6 @@ For the purposes of following best practices, it’s helpful to break the error "zonesWithCapacity": "us-central1-f,us-central1-c" } }, -<<<<<>>>>> { "@type": "type.googleapis.com/google.rpc.LocalizedMessage", "locale": "en-US", @@ -55,9 +51,8 @@ For the purposes of following best practices, it’s helpful to break the error Consider trying your request in the zone(s), which currently has/have capacity to accommodate your request. Alternatively, you can try your request again with a different VM hardware configuration or at a later time. - For more information, see the troubleshooting documentation."<<>>>>> { "@type": "type.googleapis.com/google.rpc.Help", "links": [ @@ -92,36 +87,17 @@ Important points: [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](ht | -| | tps://github.com/googleapis/googleapi | -| | s/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. | -|---------------------------------------|---------------------------------------| - +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) From 5f06793f2b7e8d20b882a7cb8804ca466bdc705b Mon Sep 17 00:00:00 2001 From: jschneider11 <38144056+jschneider11@users.noreply.github.com> Date: Tue, 23 Jan 2024 01:12:03 +0000 Subject: [PATCH 06/11] Fixed JSON, removed text referencing rtables. changed all tables to bulleted lists. --- aip/general/0193.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aip/general/0193.md b/aip/general/0193.md index 0467ce154..93fd75331 100644 --- a/aip/general/0193.md +++ b/aip/general/0193.md @@ -121,6 +121,10 @@ 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** | +---------------------------------------+---------------------------------------+ From e531e3b22b3092dcdd77e8a448ed655adcad0628 Mon Sep 17 00:00:00 2001 From: jschneider11 <38144056+jschneider11@users.noreply.github.com> Date: Tue, 23 Jan 2024 01:16:05 +0000 Subject: [PATCH 07/11] Committing changes again: Fixed JSON, text referring to tables, moved tables to bulleted lists. --- aip/general/0193.md | 218 ++++++++++---------------------------------- 1 file changed, 48 insertions(+), 170 deletions(-) diff --git a/aip/general/0193.md b/aip/general/0193.md index 93fd75331..5541f0fff 100644 --- a/aip/general/0193.md +++ b/aip/general/0193.md @@ -47,11 +47,7 @@ For the purposes of following best practices, it’s helpful to break the error { "@type": "type.googleapis.com/google.rpc.LocalizedMessage", "locale": "en-US", - "message": "An VM instance with is currently unavailable in the zone. - Consider trying your request in the zone(s), which currently has/have capacity - to accommodate your request. - Alternatively, you can try your request again with a different VM hardware configuration or at a later time. - For more information, see the troubleshooting documentation." + "message": "An VM instance with is currently unavailable in the zone. Consider trying your request in the zone(s), which currently has/have capacity to accommodate your request. Alternatively, you can try your request again with a different VM hardware configuration or at a later time. For more information, see the troubleshooting documentation." }, { "@type": "type.googleapis.com/google.rpc.Help", @@ -77,17 +73,15 @@ Services must return a [google.rpc.Status](https://github.com/googleapis/googlea **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) +##### [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 | -| | , zone(s), which currently has/have c | -| | apacity to accommodate your request.` | -| | | -| | `Alternatively, you can try your req | -| | uest again with a different VM hardwa | -| | re configuration or at a later time.` | -| | | -| | If the error resolution exceeds the | -| | number of characters supported in the | -| | problem description (`message` string | -| | of `google.rpc.Status`), or requires | -| | multiple troubleshooting steps, | -| | include the most common resolution in | -| | the message and use the `HelpLink` | -| | payload to link to relevant | -| | documentation. | -+---------------------------------------+---------------------------------------+ +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 , zone(s), which currently has/have capacity to accommodate your request. `Alternatively, you can try your request again with a different VM hardware configuration or at a later time.` + * If the error resolution exceeds the number of characters supported in the problem description (`message` string of `google.rpc.Status`), or requires multiple troubleshooting steps, include the most common resolution in the message and use the `HelpLink` payload to link to relevant documentation. ##### HelpLink payload @@ -327,23 +214,14 @@ Provide this information in addition to a clear problem definition and actionabl [HelpLink payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L256) -+---------------------------------------+---------------------------------------+ -| **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 | -+---------------------------------------+---------------------------------------+ +Details of this object are summarized in the following ields, field descriptions, and examples: + +* `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 ### Error messages From 4dbc775d7157470999aafa2408690252b211b8c7 Mon Sep 17 00:00:00 2001 From: jschneider11 <38144056+jschneider11@users.noreply.github.com> Date: Fri, 2 Feb 2024 23:51:46 +0000 Subject: [PATCH 08/11] Committing pre-formatted content from Andrei --- aip/general/0193.md | 492 +++++++++++++++++++++++++++++++------------- 1 file changed, 345 insertions(+), 147 deletions(-) diff --git a/aip/general/0193.md b/aip/general/0193.md index 5541f0fff..0884b7e1c 100644 --- a/aip/general/0193.md +++ b/aip/general/0193.md @@ -8,23 +8,44 @@ placement: --- # Errors -Effective error communication is an important part of designing simple and intuitive APIs. Services returning standardized error responses enable API clients to construct centralized common error handling logic. This common logic simplifies API client applications and eliminates the need for cumbersome custom error handling code. +Effective error communication is an important part of designing simple and +intuitive APIs. Services returning standardized error responses enable API +clients to construct centralized common error handling logic. This common logic +simplifies API client applications and eliminates the need for cumbersome custom +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 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`, `ErrorInfo.metadata` (found on the _required_ `ErrorInfo`). For example, the `metadata` map for the sample error message above will include _at least_ the following key/value pairs: +All dynamic variables found in error messages **must** also be present in the +`map`, `ErrorInfo.metadata` (found on the *required* +`ErrorInfo`). For example, the `metadata` map for the sample error message above +will include *at least* the following key/value pairs: ``` bookTitle: "The Great Gatsby" @@ -166,7 +263,8 @@ library: "Garfield East" expectedReturnDate: "2199-05-13" ``` -The following example shows an additional example of a metadata map for information about virtual machines: +The following example shows an additional example of a metadata map for +information about virtual machines: ``` vmType: "", @@ -174,114 +272,183 @@ attachment: "" zone: "" ``` -Dynamic variables that do not appear in an error message **may** also be included in `metadata` to provide additional information to the client to be used programmatically. +Dynamic variables that do not appear in an error message **may** also be +included in `metadata` to provide additional information to the client to be +used programmatically. -Once present in `metadata`, keys **must** continue to be included in the map for the error payload to be backwards compatible, even if the value for a particular key is empty. Keys **must** be expressed as lower camel-case. +Once present in `metadata`, keys **must** continue to be included in the map for +the error payload to be backwards compatible, even if the value for a particular +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. +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 , zone(s), which currently has/have capacity to accommodate your request. `Alternatively, you can try your request again with a different VM hardware configuration or at a later time.` - * If the error resolution exceeds the number of characters supported in the problem description (`message` string of `google.rpc.Status`), or requires multiple troubleshooting steps, include the most common resolution in the message and use the `HelpLink` payload to link to relevant documentation. - +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 , + zone(s), which currently has/have capacity to + accommodate your request.`Alternatively, you can try your request + again with a different VM hardware configuration or at a later + time.` + * If the error resolution exceeds the number of characters supported in + the problem description (`message` string of `google.rpc.Status`), or + requires multiple troubleshooting steps, include the most common + resolution in the message and use the `HelpLink` payload to link to + relevant documentation. ##### HelpLink payload -When `LocalizedMessage.message` doesn’t provide the user sufficient context or actionable next steps, or if there are multiple points of failure that need to be considered in troubleshooting, a link to supplemental troubleshooting documentation **must** be provided in the `HelpLink `payload. +When `LocalizedMessage.message` doesn’t provide the user sufficient context or +actionable next steps, or if there are multiple points of failure that need to +be considered in troubleshooting, a link to supplemental troubleshooting +documentation **must** be provided in the `HelpLink`payload. -Provide this information in addition to a clear problem definition and actionable resolution, not as an alternative to them; for example. +Provide this information in addition to a clear problem definition and +actionable resolution, not as an alternative to them; for example. ``` - For more information, see the troubleshooting documentation: https://cloud.google.com/compute/docs/resource-error. + For more information, see the troubleshooting documentation: https://cloud.google.com/compute/docs/resource-error. ``` [HelpLink payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L256) -Details of this object are summarized in the following ields, field descriptions, and examples: +Details of this object are summarized in the following ields, field +descriptions, and examples: -* `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 +* `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 ### Error messages -The following sections describe best practices for error messages not described previously. +The following sections describe best practices for error messages not described +previously. #### Changing error messages ##### Method -The method of changing error messages depends on whether an ErrorInfo payload is present in the message. +The method of changing error messages depends on whether an ErrorInfo payload is +present in the message. If the error message contains ErrorInfo payload (a machine-readable identifier): -* `Status.message` _string_ and `LocalizedMessage.message` _string_ can change +* `Status.message` *string* and `LocalizedMessage.message` *string* can change * New metadata fields can be added -* However, existing metadata fields **must not** be removed and existing metadata field keys cannot be modified. +* However, existing metadata fields **must not** be removed and existing + metadata field keys cannot be modified. -If the error message does _not_ contain ErrorInfo payload (usually for pre-existing APIs): +If the error message does *not* contain ErrorInfo payload (usually for +pre-existing APIs): -* The `LocalizedMessage.message` _string_ can change -* However, the `Status.message` _string_ **must** not be changed, as this change is backward-incompatible. +* The `LocalizedMessage.message` *string* can change +* However, the `Status.message` *string* **must** not be changed, as this + change is backward-incompatible. ##### Message alignment -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". +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 VM instance with is currently unavailable in the zone. Consider trying your request in the zone(s), which currently has/have capacity to accommodate your request. Alternatively, you can try your request again with a different VM hardware configuration or at a later time. For more information, see the troubleshooting documentation." - }, - { - "@type": "type.googleapis.com/google.rpc.Help", - "links": [ - { - "description": "Additional information on this error", - "url": "https://cloud.google.com/compute/docs/resource-error" - } - ] - } - ] - } + "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 VM instance with is currently unavailable in the zone. Consider trying your request in the zone(s), which currently has/have capacity to accommodate your request. Alternatively, you can try your request again with a different VM hardware configuration or at a later time. For more information, see the troubleshooting documentation." + }, + { + "@type": "type.googleapis.com/google.rpc.Help", + "links": [ + { + "description": "Additional information on this error", + "url": "https://cloud.google.com/compute/docs/resource-error" + } + ] + } + ] + } } ``` + #### google.rpc.Status Services must return 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) 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: +[`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 , zone(s), which currently has/have capacity to - accommodate your request.`Alternatively, you can try your request + accommodate your request. Alternatively, you can try your request again with a different VM hardware configuration or at a later time.` * If the error resolution exceeds the number of characters supported in @@ -339,7 +347,7 @@ Provide this information in addition to a clear problem definition and actionable resolution, not as an alternative to them; for example. ``` - For more information, see the troubleshooting documentation: https://cloud.google.com/compute/docs/resource-error. + For more information, see the troubleshooting documentation: https://cloud.google.com/compute/docs/resource-error. ``` [HelpLink payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L256) @@ -355,13 +363,16 @@ descriptions, and examples: standardized format listed in the following example. * *Example*: https://cloud.google.com/PRODUCT/docs/ERROR-REASON + ### Error messages The following sections describe best practices for error messages not described previously. + #### Changing error messages + ##### Method The method of changing error messages depends on whether an ErrorInfo payload is @@ -379,7 +390,7 @@ pre-existing APIs): * The `LocalizedMessage.message` *string* can change * However, the `Status.message` *string* **must** not be changed, as this - change is backward-incompatible. + change is backward-incompatible. ##### Message alignment @@ -390,10 +401,10 @@ 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) +[`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 Date: Tue, 20 Feb 2024 04:46:56 -0800 Subject: [PATCH 11/11] Fix whitespace, especially line width. * Restrict line width to 80 characters, applying standards for md format, e.g wrapping for links, etc. * Add whitespace after head matter. * Format bullets using dashes instead of astrices, to match style of the other AIPs. --- aip/general/0193.md | 694 +++++++++++++++++++++++--------------------- 1 file changed, 360 insertions(+), 334 deletions(-) diff --git a/aip/general/0193.md b/aip/general/0193.md index e2fe23397..ef2e255a0 100644 --- a/aip/general/0193.md +++ b/aip/general/0193.md @@ -6,34 +6,38 @@ placement: category: polish order: 30 --- + # Errors -Effective error communication is an important part of designing simple and -intuitive APIs. Services returning standardized error responses enable API -clients to construct centralized common error handling logic. This common logic -simplifies API client applications and eliminates the need for cumbersome custom -error handling code. +Effective error communication is an important part of designing simple +and intuitive APIs. Services returning standardized error responses +enable API clients to construct centralized common error handling logic. +This common logic simplifies API client applications and eliminates the +need for cumbersome custom 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 -error codes defined in +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). +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) +**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. @@ -45,45 +49,46 @@ when writing messages. 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 { - "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 VM instance with is currently unavailable in the zone. Consider trying your request in the zone(s), which currently has/have capacity to accommodate your request. Alternatively, you can try your request again with a different VM hardware configuration or at a later time. For more information, see the troubleshooting documentation." - }, - { - "@type": "type.googleapis.com/google.rpc.Help", - "links": [ - { - "description": "Additional information on this error", - "url": "https://cloud.google.com/compute/docs/resource-error" - } - ] - } - ] - } + "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 VM instance with is currently unavailable in the zone. Consider trying your request in the zone(s), which currently has/have capacity to accommodate your request. Alternatively, you can try your request again with a different VM hardware configuration or at a later time. For more information, see the troubleshooting documentation." + }, + { + "@type": "type.googleapis.com/google.rpc.Help", + "links": [ + { + "description": "Additional information on this error", + "url": "https://cloud.google.com/compute/docs/resource-error" + } + ] + } + ] + } } ``` @@ -92,34 +97,38 @@ is often different from how the error is presented to users. 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: +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)) +- 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™. +**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). +- 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) @@ -128,143 +137,146 @@ 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. +- `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 +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 +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) +[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). +- `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. +`LocalizedMessage.message`, which is subject to change and is not part +of the 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 -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`, `ErrorInfo.metadata` (found on the *required* -`ErrorInfo`). For example, the `metadata` map for the sample error message above -will include *at least* the following key/value pairs: +All dynamic variables found in error messages **must** also be present +in the `map`, `ErrorInfo.metadata` (found on the +*required* `ErrorInfo`). For example, the `metadata` map for the sample +error message above will include *at least* the following key/value +pairs: ``` bookTitle: "The Great Gatsby" @@ -282,92 +294,98 @@ zone: "" ``` Dynamic variables that do not appear in an error message **may** also be -included in `metadata` to provide additional information to the client to be -used programmatically. +included in `metadata` to provide additional information to the client +to be used programmatically. -Once present in `metadata`, keys **must** continue to be included in the map for -the error payload to be backwards compatible, even if the value for a particular -key is empty. Keys **must** be expressed as lower camel-case. +Once present in `metadata`, keys **must** continue to be included in the +map for the error payload to be backwards compatible, even if the value +for a particular 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. +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) +[LocalizedMessage +Payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L277) Details of this object are summarized in the following fields, 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 , - zone(s), which currently has/have capacity to - accommodate your request. Alternatively, you can try your request - again with a different VM hardware configuration or at a later - time.` - * If the error resolution exceeds the number of characters supported in - the problem description (`message` string of `google.rpc.Status`), or - requires multiple troubleshooting steps, include the most common - resolution in the message and use the `HelpLink` payload to link to - relevant documentation. +- `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 , + zone(s), which currently has/have capacity to + accommodate your request. Alternatively, you can try your request + again with a different VM hardware configuration or at a later + time.` + - If the error resolution exceeds the number of characters supported + in the problem description (`message` string of + `google.rpc.Status`), or requires multiple troubleshooting steps, + include the most common resolution in the message and use the + `HelpLink` payload to link to relevant documentation. ##### HelpLink payload -When `LocalizedMessage.message` doesn’t provide the user sufficient context or -actionable next steps, or if there are multiple points of failure that need to -be considered in troubleshooting, a link to supplemental troubleshooting -documentation **must** be provided in the `HelpLink`payload. +When `LocalizedMessage.message` doesn’t provide the user sufficient +context or actionable next steps, or if there are multiple points of +failure that need to be considered in troubleshooting, a link to +supplemental troubleshooting documentation **must** be provided in the +`HelpLink`payload. Provide this information in addition to a clear problem definition and actionable resolution, not as an alternative to them; for example. ``` - For more information, see the troubleshooting documentation: https://cloud.google.com/compute/docs/resource-error. +For more information, see the troubleshooting documentation: https://cloud.google.com/compute/docs/resource-error. ``` -[HelpLink payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L256) +[HelpLink +payload](https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L256) Details of this object are summarized in the following ields, field descriptions, and examples: -* `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 +- `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 ### Error messages -The following sections describe best practices for error messages not described -previously. +The following sections describe best practices for error messages not +described previously. #### Changing error messages @@ -375,92 +393,96 @@ previously. ##### Method -The method of changing error messages depends on whether an ErrorInfo payload is -present in the message. +The method of changing error messages depends on whether an ErrorInfo +payload is present in the message. -If the error message contains ErrorInfo payload (a machine-readable identifier): +If the error message contains ErrorInfo payload (a machine-readable +identifier): -* `Status.message` *string* and `LocalizedMessage.message` *string* can change -* New metadata fields can be added -* However, existing metadata fields **must not** be removed and existing - metadata field keys cannot be modified. +- `Status.message` *string* and `LocalizedMessage.message` *string* can change +- New metadata fields can be added +- However, existing metadata fields **must not** be removed and existing + metadata field keys cannot be modified. If the error message does *not* contain ErrorInfo payload (usually for pre-existing APIs): -* The `LocalizedMessage.message` *string* can change -* However, the `Status.message` *string* **must** not be changed, as this - change is backward-incompatible. +- The `LocalizedMessage.message` *string* can change +- However, the `Status.message` *string* **must** not be changed, as + this change is backward-incompatible. ##### Message alignment 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. +`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 +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. +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, +- 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 +- 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 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 +- 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 @@ -476,27 +498,28 @@ Consider trying your request in the us-central1-f, us-central1-c zone(s), which currently has/have capacity to accommodate your request. Alternatively, you can try your request again with a different VM -hardware configuration or at a later time. For more information, see -the troubleshooting documentation: +hardware configuration or at a later time. For more information, see the +troubleshooting documentation: 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. +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 +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. @@ -505,11 +528,12 @@ object. 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. +`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 @@ -517,58 +541,60 @@ does not exist, the service **must** error with `NOT_FOUND` (HTTP 404). ### 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 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. -- **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 +- **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.