@@ -240,64 +240,36 @@ authentication.
240240
241241### Error messages
242242
243- The following sections describe best practices for error messages not
244- described previously.
243+ Textual error messages can be present in both ` Status.message ` and
244+ ` LocalizedMessage.message ` fields. Messages should be succinct but
245+ actionable, with request-specific information (such as a resource name
246+ or region) providing precise details where appropriate. Any request-specific
247+ details ** must** be present in [ ` ErrorInfo.metadata ` ] ( #errorinfo ) .
245248
246249#### Changing error messages
247250
248- ##### Method
251+ Changing the content of ` Status.message ` over time must be done carefully,
252+ to avoid breaking clients who have previously had to rely on the message
253+ for all information. See [ the rationale section] ( #updating-statusmessage )
254+ for more details.
249255
250- The method of changing error messages depends on whether an ErrorInfo
251- payload is present in the message.
256+ For a given RPC:
252257
253- If the error message contains ErrorInfo payload (a machine-readable
254- identifier):
258+ - If the RPC has * always* returned ` ErrorInfo ` with machine-readable
259+ information, the content of ` Status.message ` ** may** change over time.
260+ (For example, the API producer may provide a clearer explanation,
261+ or more request-specific information.)
262+ - Otherwise, the content of ` Status.message ` ** must** be stable,
263+ providing the same text with the same request-specific information.
264+ Instead of changing ` Status.message ` , the API ** should** include a
265+ [ ` LocalizedMessage ` ] ( #localizedmessage ) within ` Status.details ` .
255266
256- - ` Status.message ` * string* and ` LocalizedMessage.message ` * string* can
257- change
258- - New metadata fields can be added
259- - However, existing metadata fields ** must not** be removed and existing
260- metadata field keys cannot be modified.
261267
262- If the error message does * not* contain ErrorInfo payload (usually for
263- pre-existing APIs):
268+ Even if an RPC has always returned ` ErrorInfo ` , the API ** may** keep
269+ the existing ` Status.message ` stable and add a
270+ [ ` LocalizedMessage ` ] ( #localizedmessage ) within ` Status.details ` .
264271
265- - The ` LocalizedMessage.message ` * string* can change
266- - However, the ` Status.message ` * string* ** must** not be changed, as
267- this change is backward-incompatible.
268-
269- ##### Message alignment
270-
271- ` LocalizedMessage ` is populated with the same message as
272- ` Status.message ` . Should you choose, you can also present a different
273- ` LocalizedMessage.message ` from ` Status.message ` . For reasons why or why not,
274- see [ the rationale] ( #LocalizedMessage ) .
275-
276- Keeping the aforementioned guidance in mind, the safest and recommended
277- method to update an error message for a service is to add
278- [ ` google.rpc.LocalizedMessage ` ] [ LocalizedMessage ] to
279- [ ` Status.details ` ] [ Status details ] . ` LocalizedMessage ` is meant for
280- displaying messages to end users.
281-
282- Add as much information as the consumer of the error needs to resolve
283- the error, but succinctly.
284-
285- When including ` LocalizedMessage ` , both ` locale ` and ` message ` ** must**
286- be populated. If the service is to be localized, the value of ` locale `
287- ** must** change dynamically. See "[ Localization] ( #localization ) ".
288- Otherwise, ` locale ` ** must** always present the service's default
289- locale; for example, "en-US".
290-
291- When adding an error message using ` LocalizedMessage ` , ` ErrorInfo `
292- ** must** be introduced either before or at the same time. If there are
293- dynamic segments found in the text, the values of these variables
294- ** must** be included in ` ErrorInfo.metadata ` . See, "[ Dynamic
295- variables] ( #dynamic-variables ) ".
296-
297- ** Warning:** If ` LocalizedMessage ` is released without ` ErrorInfo ` , the
298- same concerns regarding changing the value of the ` message ` field of
299- ` LocalizedMissage ` apply: clients may misuse this textual error
300- message--matching on string content.
272+ The content of ` LocalizedMessage.details ` ** may** change over time.
301273
302274### Partial errors
303275
@@ -445,16 +417,24 @@ differs from `Status.message` include the following:
445417
446418### Updating Status.message
447419
448- ** Because Status.message is part of the API contract** , avoid updating
449- it entirely in favor of updating LocalizedMessage; for example, clients
450- often perform string matches on the text to differentiate one error for
451- another and even parse the error message to extract variables from
452- dynamic segments.
453-
454- Clients ** must** only perform string matches if their only option for
455- extracting dynamic information is the message itself. If structured data
456- is present in metadata, the recommended practice is to key into that
457- data instead.
420+ If a client has ever observed an error with ` Status.message ` populated
421+ (which it always will be) but without ` ErrorInfo ` , the developer of that client
422+ may well have had to resort to parsing ` Status.message ` in order to find out
423+ information beyond just what ` Status.code ` conveys. That information may be
424+ found by matching specific text (e.g. "Connection closed with unknown cause")
425+ or by parsing the message to find out metadata values (e.g. a region with
426+ insufficient resources). At that point, ` Status.message ` is implicitly part
427+ of the API contract, so ** must not** be updated - that would be a breaking
428+ change. This is one reason for introducing ` LocalizedMessage ` into the
429+ ` Status.details ` .
430+
431+ RPCs which have ** always** included ` ErrorInfo ` are in a better position:
432+ the contract is then more about the stability of ` ErrorInfo ` for any given
433+ error: the reason and domain need to be consistent over time, and the
434+ metadata provided for any given (reason,domain) can only be expanded.
435+ It's still possible that clients could be parsing ` Status.message ` instead of
436+ using ` ErrorInfo ` , but they will always have had a more robust option
437+ available to them.
458438
459439## Further reading
460440
0 commit comments