@@ -32,6 +32,39 @@ Error messages **should** be brief but actionable. Any extra information
3232necessary, you ** should** provide a link where a reader can get more
3333information or ask questions to help resolve the issue.
3434
35+
36+ A JSON representation of an error response might look like the
37+ following:
38+
39+ <a name =" sample " ></a >
40+
41+ ``` json
42+ {
43+ "error" : {
44+ "code" : 429 ,
45+ "message" : " The zone 'us-east-1' does not have enough resources available to fulfill the request. Try a different zone, or try again later." ,
46+ "status" : " RESOURCE_EXHAUSTED" ,
47+ "details" : [
48+ {
49+ "@type" : " type.googleapis.com/google.rpc.ErrorInfo" ,
50+ "reason" : " STOCKOUT" ,
51+ "domain" : " compute.googleapis.com" ,
52+ "metadata" : {
53+ "zone" : " us-east1-a" ,
54+ "vmType" : " e2-medium" ,
55+ "attachment" : " local-ssd=3,nvidia-t4=2"
56+ }
57+ },
58+ {
59+ "@type" : " type.googleapis.com/google.rpc.LocalizedMessage" ,
60+ "locale" : " en-US" ,
61+ "message" : " A e2-medium with local-ssd=3,nvidia-t4=2 is currently unavailable in the us-east1-a zone.\n Capacity changes frequently, so try your request in a different zone, with a different VM hardware configuration, or at a later time. For more information, see troubleshooting documentation."
62+ }
63+ ]
64+ }
65+ }
66+ ```
67+
3568### Details
3669
3770Google defines a set of [ standard detail payloads] [ details ] for error details,
@@ -62,11 +95,117 @@ a [`PreconditionFailure`][PreconditionFailure].
6295** Note:** ` ErrorInfo ` represents a special case. There ** must** be exactly one
6396` ErrorInfo ` . It is required.
6497
65- ### Localization
98+ ### Error messages
99+
100+ For each error, the service ** must** populate the ` message ` field on
101+ [ ` google.rpc.Status ` ] [ Status ] . This error message,
102+
103+ - is a developer-facing, human-readable "debug message"
104+ - is presented in the service's native language
105+ - both explains the error and offers an actionable resolution to it
106+ ([ citation] ( https://cloud.google.com/apis/design/errors#error_model ) )
107+
108+ ** Note:** Sometimes a service will elect to always present
109+ ` Status.message ` in English rather than the application's native
110+ language so that messages are easily searchable in common knowledge
111+ bases, such as StackOverflow&trade ; .
112+
113+ When introducing an error that represents a failure scenario that did
114+ not previously occur for the service, the payload ** must** include
115+ ` ErrorInfo ` and any variables found in dynamic segments of the error
116+ message ** must** be present in ` ErrorInfo.metadata ` . See, "[ Dynamic
117+ variables] ( #dynamic-variables ) ".
118+
119+ #### Changing error messages
120+
121+ <a name =" status-message-warning " ></a >
122+
123+ ` Status.message ` ** may** change. However, ** use extreme caution** when
124+ doing so. API consumers often treat this error message as ** part of the
125+ API contract** . Clients perform string matches on the text to
126+ differentiate one error for another and even parse the error message to
127+ extract variables from dynamic segments.
128+
129+ There is a safer alternative. The service can chose to include an error
130+ message by adding [ ` google.rpc.LocalizedMessage ` ] [ LocalizedMessage ] to
131+ [ ` Status.details ` ] [ Status details ] .
132+
133+ The error message presented in ` LocalizedMessage.message ` ** may** be the
134+ same as ` Status.message ` or it ** may** be an alternate message.
135+
136+ Reasons to present the same error message in both locations include the
137+ following:
138+
139+ - The service plans to localize either immediately or in the near
140+ future. See, "[ Localization] ( #localization ) ".
141+ - It affords clients the ability to find an error message consistently
142+ in one location, ` LocalizedMessaage.message ` , across all methods of
143+ the API Service.
144+
145+ Reasons to present an error message in ` LocalizedMessage.message ` that
146+ differs from ` Status.message ` include the following:
147+
148+ - The service requires an end-user facing error message that differs
149+ from the "debug message".
150+ - Ongoing, iterative error message improvements are expected.
66151
67- Error messages ** must** be in English. If a localized error message is also
68- required, the service ** should** use [ ` google.rpc.LocalizedMessage ` ] [ details ]
69- in the ` details ` field.
152+ When including ` LocalizedMessage ` , both fields, ` locale ` and ` message ` ,
153+ ** must** be populated. If the service is to be localized, the value of
154+ ` locale ` ** must** change dynamically. See,
155+ "[ Localization] ( #localization ) ". Otherwise, ` locale ` ** must** always
156+ present the service's default locale, e.g. "en-US".
157+
158+ When adding an error message via ` LocalizedMessage ` , ` ErrorInfo `
159+ ** must** be introduced either before or at the same time. If there are
160+ dynamic segments found in the text, the values of these variables
161+ ** must** be included in ` ErrorInfo.metadata ` . See, "[ Dynamic
162+ variables] ( #dynamic-variables ) ".
163+
164+ ** Warning:** If ` LocalizedMessage ` is released without ` ErrorInfo ` , the
165+ same [ concerns] ( #status-message-warning ) regarding client misuse of
166+ textual error messages apply.
167+
168+ #### Dynamic variables
169+
170+ The best, actionable error messages include dynamic segments. These
171+ variable parts of the message are specific to a particular request.
172+ Consider the following example:
173+
174+ > The Book, "The Great Gatsby", is unavailable at the Library, "Garfield
175+ > East". It is expected to be available again on 2199-05-13.
176+
177+ The preceding error message is made actionable by the context, both that
178+ originates from the request, the title of the Book and the name of the
179+ Library, and by the information that is known only by the service, i.e.
180+ the expected return date of the Book.
181+
182+ All dynamic variables found in error messages ** must** also be present
183+ in the ` map<string, string> ` , ` ErrorInfo.metadata ` (found on the
184+ * required* ` ErrorInfo ` ). For example, the ` metadata ` map for the sample
185+ error message above will include * at least* the following key/value
186+ pairs:
187+
188+ ``` yaml
189+ bookTitle : " The Great Gatsby"
190+ library : " Garfield East"
191+ expectedReturnDate : " 2199-05-13"
192+ ` ` `
193+
194+ Dynamic variables that do not appear in an error message **may** also be
195+ included in ` metadata` to provide additional information to the client
196+ to be used programmatically.
197+
198+ Once present in `metadata`, keys **must** continue to be included in the
199+ map for the error payload to be backwards compatible, even if the value
200+ for a particular key is empty. Keys **must** be expressed as lower
201+ camel-case.
202+
203+ # ### Localization
204+
205+ The value of `Status.message` **should** be presented in the service's
206+ native language. If a localized error message is required, the service
207+ **must** include [`google.rpc.LocalizedMessage`][LocalizedMessage] in
208+ ` Status.details` .
70209
71210# ## Partial errors
72211
@@ -96,16 +235,26 @@ does not exist, the service **must** error with `NOT_FOUND` (HTTP 404).
96235
97236# # Rationale
98237
99- ` ErrorInfo ` is required because it further identifies an error. The
100- ` Status ` field, with under 20 [ allowed values] [ Code ] , is rarely enough
101- to disambiguate one error from another accross an entire API Service.
102- Error messages often contain dynamic segments that express values, such
103- as project numbers or locations, and these values are often read from
104- the string message using brittle extraction methods, like RegExp. There
105- needs to be a machine readable component of * every* error response that
106- enables clients to pull such information programatically--without
107- parsing the string error message. For these reasons, ` ErrorInfo ` is
108- required for * every* error response.
238+ # ## Requiring ErrorInfo
239+
240+ ` ErrorInfo` is required because it further identifies an error. With
241+ only approximately twenty [available values][Code] for `Status.status`,
242+ it is difficult to disambiguate one error from another across an entire
243+ [API Service][API Service].
244+
245+ Also, error messages often contain dynamic segments that express
246+ variable information, so there needs to be machine readable component of
247+ *every* error response that enables clients to use such information
248+ programmatically.
249+
250+ # ## LocalizedMessage
251+
252+ ` LocalizedMessage` was selected as the location to present alternate
253+ error messages. This is desirable when clients need to display a crafted
254+ error message directly to end users. `LocalizedMessage` can be used with
255+ a static `locale`. This may seem misleading, but it allows the service
256+ to eventually localize without having to duplicate or move the error
257+ message, which would be a backwards incompatible change.
109258
110259# # Further reading
111260
@@ -115,6 +264,9 @@ required for *every* error response.
115264
116265# # Changelog
117266
267+ - **2023-05-17**: Change the recommended language for `Status.message`
268+ to be the service's native language rather than English.
269+ - **2023-05-17**: Specify requirements for changing error messages.
118270- **2023-05-10**: Require [`ErrorInfo`][ErrorInfo] for all error
119271 responses.
120272- **2023-05-04**: Require uniqueness by message type for error details.
@@ -133,8 +285,11 @@ required for *every* error response.
133285[ErrorInfo] : https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L27-L76
134286[PreconditionFailure] : https://github.com/googleapis/googleapis/blob/6f3fcc058ff29989f6d3a71557a44b5e81b897bd/google/rpc/error_details.proto#L139-L166
135287[BadRequest] : https://github.com/googleapis/googleapis/blob/477a59d764428136ba1d857a9633c0d231de6efa/google/rpc/error_details.proto#L168-L218
288+ [LocalizedMessage] : https://github.com/googleapis/googleapis/blob/e9897ed945336e2dc967b439ac7b4be6d2c62640/google/rpc/error_details.proto#L275-L285
136289[grpc status code documentation] : https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
137290[Code] : https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto
138291[Status] : https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto
292+ [Status details] : https://github.com/googleapis/googleapis/blob/aeae5ea2b01ece6c0cee046ae84b881cdc62b95d/google/rpc/status.proto#L46-L48
139293[long-running operations] : ./0151.md
294+ [API Service] : https://cloud.google.com/apis/design/glossary#api_service
140295<!-- prettier-ignore-end -->
0 commit comments