Skip to content

Commit 4cb8766

Browse files
committed
Rewrite ErrorInfo description
Note: this has removed the term "dynamic variables" in favor of only referring to it as "metadata". It's handy to have a single well-defined term, and given that the field name is `metatadata`, I've kept that.
1 parent 7da247d commit 4cb8766

1 file changed

Lines changed: 61 additions & 101 deletions

File tree

aip/general/0193.md

Lines changed: 61 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ developers to understand the problem and is more detailed than
5151

5252
Messages **should** use simple descriptive language that is easy to understand
5353
(without technical jargon) to clearly state the problem that results in an
54-
error.
54+
error, and offer an actionable resolution to it.
5555

56-
For pre-existing (brownfield) APIs which have returned errors without
57-
additional details in the past, the value of `message` must remain the same
58-
for any given error, as developers have previously had no option but to use
59-
this for error handling. For more information, see
56+
For pre-existing (brownfield) APIs which have previously returned errors
57+
without machine-readable identifiers, the value of `message` **must**
58+
remain the same for any given error, as developers have previously had no
59+
option but to use this for error handling. For more information, see
6060
[Changing Error Messages](#changing-error-messages).
6161

6262
### Status.code
@@ -96,121 +96,81 @@ The following sections describe the most common standard detail payloads.
9696

9797
#### ErrorInfo
9898

99-
The [`ErrorInfo`][ErrorInfo] message is the required way to send a
100-
machine-readable identifier. All error responses **must** include an
101-
`ErrorInfo` payload in `details`. Variable information **should** be
99+
The [`ErrorInfo`][ErrorInfo] message is the primary way to send a
100+
machine-readable identifier. Contextual information **should** be
102101
included in `metadata` in `ErrorInfo` and **must** be included if it
103102
appears within an error message.
104103

105-
When introducing an error that represents a failure scenario that did
106-
not previously occur for the service, the payload **must** include
107-
`ErrorInfo` and any variables found in dynamic segments of the error
108-
message **must** be present in `ErrorInfo.metadata` (See [Dynamic
109-
variables](#dynamic-variables).)
104+
The `reason` field is a short snake_case description of the cause of the
105+
error. Error reasons are unique within a particular domain of errors.
106+
The reason **must** be at most 63 characters and match a regular expression of
107+
`[A-Z][A-Z0-9_]+[A-Z0-9]`. (This is UPPER_SNAKE_CASE, without leading
108+
or trailing underscores, and without leading digits.)
110109

111-
**Note:** `ErrorInfo` represents a special case. There **must** be
112-
exactly one `ErrorInfo`. It is required.
110+
The reason should be terse, but meaningful enough for a human reader to
111+
understand what the reason refers to.
113112

114-
[ErrorInfo Payload][ErrorInfo]
113+
Good examples:
115114

116-
Details of this object are summarized in the following fields, field
117-
descriptions, and examples:
115+
- `CPU_AVAILABILITY`
116+
- `NO_STOCK`
117+
- `CHECKED_OUT`
118+
- `AVAILABILITY_ERROR`
118119

119-
- `reason string`
120-
- A short snake_case description of why the error occurred. Error
121-
reasons are unique within a particular domain of errors. The error
122-
reason **must** do the following:
123-
- Be at most 63 characters and match a regular expression of
124-
`/[A-Z][A-Z0-9_]+[A-Z0-9]/`, which represents UPPER_SNAKE_CASE.
125-
- Be meaningful enough for a human reader to understand what the
126-
reason refers to.
127-
- Be unique and consumable by machine actors for automation.
128-
- *Example*: CPU_AVAILABILITY<br>
129-
Distill your error message into its simplest form. For example, the
130-
`reason string` could be one of the following text examples in
131-
UPPER_SNAKE_CASE: `UNAVAILABLE`, `NO_STOCK`, `CHECKED_OUT`,
132-
`AVAILABILITY_ERROR`, if your error message is,
133-
134-
> The Book, "The Great Gatsby", is unavailable at the Library,
135-
> "Garfield East". It is expected to be available again on 2199-05-13.
136-
137-
- In contrast, using either of the following reasons is not
138-
recommended: `THE_BOOK_YOU_WANT_IS_NOT_AVAILABLE`, `ERROR`. And,
139-
using either of the following reasons breaches the required
140-
formatting and is not allowed: `librariesAreGreat`, `noBooks`.
141-
142-
- `domain string`
143-
- The logical grouping to which the `reason` belongs. The error domain
144-
is typically the registered service name of the tool or product that
145-
generated the error. The domain must be a globally unique value.
146-
- *Example*:<br>`pubsub.googleapis.com`
147-
148-
- `metadata map`
149-
- Additional structured details about this error, which **should**
150-
provide important context for customers to identify resolution
151-
steps. Keys **should** match `/[a-z][a-zA-Z0-9-_]+/`, and be
152-
limited to 64 characters in length. When identifying the current
153-
value of an exceeded limit, the units **should** be contained in the
154-
key, not the value.
155-
- *Example*:
156-
```
157-
"vmType": "e2-medium",
158-
"attachment": "local-ssd=3,nvidia-t4=2",
159-
"zone": "us-east1-a"
160-
```
161-
- For guidance on using the metadata map, see [Dynamic
162-
Variables](#dynamic-variables).
120+
Bad examples:
163121

164-
##### Dynamic variables
122+
- `THE_BOOK_YOU_WANT_IS_NOT_AVAILABLE` (overly verbose)
123+
- `ERROR` (too general)
165124

166-
The best, actionable error messages include dynamic segments. These
167-
variable parts of the message are specific to a particular request.
168-
Without such context, it is unlikely that the message will be fully
169-
actionable by the user.
125+
The `domain` field is the logical grouping to which the `reason` belongs.
126+
The domain **must** be a globally unique value, and is typically the name of the service
127+
that generated the error, e.g. `pubsub.googleapis.com`.
170128

171-
This practice is critical so that machine actors do not need to rely on
172-
`LocalizedMessage.message`, which is subject to change and is not part
173-
of the API contract.
129+
The (reason, domain) pair form a machine-readable way of identifying a particular error.
130+
Services **must** use the same (reason, domain) pair for the same error, and
131+
**must not** use the same (reason, domain) pair for logically different errors.
132+
The decision about whether two errors are "the same" or not is not always clear, but
133+
**should** generally be considered in terms of the expected action a client might take
134+
to resolve them.
174135

175-
Consider the following example:
136+
The `metadata` field is a map of key/value pairs providing additional
137+
dynamic information as context. Each key within `metadata` **must** be at most
138+
64 characters long, and conform to the regular expression `[a-z][a-zA-Z0-9-_]+`.
176139

177-
> The Book, "The Great Gatsby", is unavailable at the Library, "Garfield
178-
> East". It is expected to be available again on 2199-05-13.
140+
Any request-specific information which contributes to the `Status.message` or
141+
`LocalizedMessage.message` messages **must** be represented within `metadata`.
142+
This practice is critical so that machine actors do not need to parse error
143+
messages to extract information.
179144

180-
The preceding error message is made actionable by the context, both
181-
originating from the request, the title of the Book, the name of the
182-
Library, and by the information that is known only by the service, that
183-
is, the expected return date of the Book.
145+
For example consider the following message:
184146

185-
All dynamic variables found in error messages **must** also be present
186-
in the `map<string, string>`, `ErrorInfo.metadata` (found on the
187-
*required* `ErrorInfo`). For example, the `metadata` map for the sample
188-
error message above will include *at least* the following key/value
189-
pairs:
147+
> An &lt;e2-medium&gt; VM instance with &lt;local-ssd=3,nvidia-t4=2&gt; is currently unavailable
148+
> in the &lt;us-east1-a&gt; zone. Consider trying your request in the &lt;us-central1-f,us-central1-c&gt;
149+
> zone(s), which currently has/have capacity to accommodate your request. Alternatively,
150+
> you can try your request again with a different VM hardware configuration
151+
> or at a later time. For more information, see the troubleshooting documentation.
190152
191-
```
192-
bookTitle: "The Great Gatsby"
193-
library: "Garfield East"
194-
expectedReturnDate: "2199-05-13"
195-
```
153+
The `ErrorInfo.metadata` map for the same error could be:
196154

197-
The following example shows an additional example of a metadata map for
198-
information about virtual machines:
155+
- `"zone": "us-east1-a"`
156+
- `"vmType": "e2-medium"`
157+
- `"attachment": "local-ssd=3,nvidia-t4=2"`
158+
- `"zonesWithCapacity": "us-central1-f,us-central1-c"`
199159

200-
```
201-
vmType: "<VM-TYPE>",
202-
attachment: "<ATTACHMENT>"
203-
zone: "<ZONE>"
204-
```
160+
Additional contextual information that does not appear in an error message
161+
**may** also be included in `metadata` to allow programmatic use by the client.
162+
163+
The metadata included for any given (reason,domain) pair can evolve over time:
164+
165+
- New keys **may** be included
166+
- All keys that have been included **must** continue to be included (but may have empty values)
205167

206-
Dynamic variables that do not appear in an error message **may** also be
207-
included in `metadata` to provide additional information to the client
208-
to be used programmatically.
168+
In other words, once a user has observed a given key for a (reason, domain) pair, the
169+
service **must** allow them to rely on it continuing to be present in the future.
209170

210-
Once present in `metadata`, keys **must** continue to be included in the
211-
map for the error payload to be backwards compatible, even if the value
212-
for a particular key is empty. Keys **must** be expressed as lower
213-
camel-case.
171+
The set of keys provided in each (reason, domain) pair is independent from other pairs,
172+
but services **should** aim for consistent key naming. For example, two error reasons
173+
within the same domain should not use metadata keys of `vmType` and `virtualMachineType`.
214174

215175
#### Localization
216176

0 commit comments

Comments
 (0)