async_nats/jetstream/
errors.rs

1// Copyright 2020-2022 The NATS Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14use std::{error, fmt};
15
16use serde::{Deserialize, Serialize};
17
18#[derive(Debug, PartialEq, Eq, Clone, Copy, Deserialize, Serialize)]
19pub struct ErrorCode(u64);
20
21impl ErrorCode {
22    /// Peer not a member
23    pub const CLUSTER_PEER_NOT_MEMBER: ErrorCode = ErrorCode(10040);
24
25    /// Consumer expected to be ephemeral but detected a durable name set in subject
26    pub const CONSUMER_EPHEMERAL_WITH_DURABLE: ErrorCode = ErrorCode(10019);
27
28    /// Stream external delivery prefix overlaps with stream subject
29    pub const STREAM_EXTERNAL_DELETE_PREFIX_OVERLAPS: ErrorCode = ErrorCode(10022);
30
31    /// Resource limits exceeded for account
32    pub const ACCOUNT_RESOURCES_EXCEEDED: ErrorCode = ErrorCode(10002);
33
34    /// Jetstream system temporarily unavailable
35    pub const CLUSTER_NOT_AVAILABLE: ErrorCode = ErrorCode(10008);
36
37    /// Subjects overlap with an existing stream
38    pub const STREAM_SUBJECT_OVERLAP: ErrorCode = ErrorCode(10065);
39
40    /// Wrong last sequence
41    pub const STREAM_WRONG_LAST_SEQUENCE: ErrorCode = ErrorCode(10071);
42
43    /// Template name in subject does not match request
44    pub const NAME_NOT_MATCH_SUBJECT: ErrorCode = ErrorCode(10073);
45
46    /// No suitable peers for placement
47    pub const CLUSTER_NO_PEERS: ErrorCode = ErrorCode(10005);
48
49    /// Consumer expected to be ephemeral but a durable name was set in request
50    pub const CONSUMER_EPHEMERAL_WITH_DURABLE_NAME: ErrorCode = ErrorCode(10020);
51
52    /// Insufficient resources
53    pub const INSUFFICIENT_RESOURCES: ErrorCode = ErrorCode(10023);
54
55    /// Stream mirror must have max message size >= source
56    pub const MIRROR_MAX_MESSAGE_SIZE_TOO_BIG: ErrorCode = ErrorCode(10030);
57
58    /// Generic error from stream deletion operation
59    pub const STREAM_DELETE_FAILED: ErrorCode = ErrorCode(10067);
60
61    /// Bad request
62    pub const BAD_REQUEST: ErrorCode = ErrorCode(10003);
63
64    /// Not currently supported in clustered mode
65    pub const NOT_SUPPORTED_IN_CLUSTER_MODE: ErrorCode = ErrorCode(10036);
66
67    /// Consumer not found
68    pub const CONSUMER_NOT_FOUND: ErrorCode = ErrorCode(10014);
69
70    /// Stream source must have max message size >= target
71    pub const SOURCE_MAX_MESSAGE_SIZE_TOO_BIG: ErrorCode = ErrorCode(10046);
72
73    /// Generic error when stream operation fails.
74    pub const STREAM_ASSIGNMENT: ErrorCode = ErrorCode(10048);
75
76    /// Message size exceeds maximum allowed
77    pub const STREAM_MESSAGE_EXCEEDS_MAXIMUM: ErrorCode = ErrorCode(10054);
78
79    /// Generic error for stream creation error with a string
80    pub const STREAM_CREATE_TEMPLATE: ErrorCode = ErrorCode(10066);
81
82    /// Invalid JSON
83    pub const INVALID_JSON: ErrorCode = ErrorCode(10025);
84
85    /// Stream external delivery prefix must not contain wildcards
86    pub const STREAM_INVALID_EXTERNAL_DELIVERY_SUBJECT: ErrorCode = ErrorCode(10024);
87
88    /// Restore failed
89    pub const STREAM_RESTORE: ErrorCode = ErrorCode(10062);
90
91    /// Incomplete results
92    pub const CLUSTER_INCOMPLETE: ErrorCode = ErrorCode(10004);
93
94    /// Account not found
95    pub const NO_ACCOUNT: ErrorCode = ErrorCode(10035);
96
97    /// General RAFT error
98    pub const RAFT_GENERAL: ErrorCode = ErrorCode(10041);
99
100    /// Jetstream unable to subscribe to restore snapshot
101    pub const RESTORE_SUBSCRIBE_FAILED: ErrorCode = ErrorCode(10042);
102
103    /// Stream deletion failed
104    pub const STREAM_DELETE: ErrorCode = ErrorCode(10050);
105
106    /// Stream external api prefix must not overlap
107    pub const STREAM_EXTERNAL_API_OVERLAP: ErrorCode = ErrorCode(10021);
108
109    /// Stream mirrors can not contain subjects
110    pub const MIRROR_WITH_SUBJECTS: ErrorCode = ErrorCode(10034);
111
112    /// Jetstream not enabled
113    pub const JETSTREAM_NOT_ENABLED: ErrorCode = ErrorCode(10076);
114
115    /// Jetstream not enabled for account
116    pub const JETSTREAM_NOT_ENABLED_FOR_ACCOUNT: ErrorCode = ErrorCode(10039);
117
118    /// Sequence not found
119    pub const SEQUENCE_NOT_FOUND: ErrorCode = ErrorCode(10043);
120
121    /// Stream mirror configuration can not be updated
122    pub const STREAM_MIRROR_NOT_UPDATABLE: ErrorCode = ErrorCode(10055);
123
124    /// Expected stream sequence does not match
125    pub const STREAM_SEQUENCE_NOT_MATCH: ErrorCode = ErrorCode(10063);
126
127    /// Wrong last msg id
128    pub const STREAM_WRONG_LAST_MESSAGE_ID: ErrorCode = ErrorCode(10070);
129
130    /// Jetstream unable to open temp storage for restore
131    pub const TEMP_STORAGE_FAILED: ErrorCode = ErrorCode(10072);
132
133    /// Insufficient storage resources available
134    pub const STORAGE_RESOURCES_EXCEEDED: ErrorCode = ErrorCode(10047);
135
136    /// Stream name in subject does not match request
137    pub const STREAM_MISMATCH: ErrorCode = ErrorCode(10056);
138
139    /// Expected stream does not match
140    pub const STREAM_NOT_MATCH: ErrorCode = ErrorCode(10060);
141
142    /// Setting up consumer mirror failed
143    pub const MIRROR_CONSUMER_SETUP_FAILED: ErrorCode = ErrorCode(10029);
144
145    /// Expected an empty request payload
146    pub const NOT_EMPTY_REQUEST: ErrorCode = ErrorCode(10038);
147
148    /// Stream name already in use with a different configuration
149    pub const STREAM_NAME_EXIST: ErrorCode = ErrorCode(10058);
150
151    /// Tags placement not supported for operation
152    pub const CLUSTER_TAGS: ErrorCode = ErrorCode(10011);
153
154    /// Maximum consumers limit reached
155    pub const MAXIMUM_CONSUMERS_LIMIT: ErrorCode = ErrorCode(10026);
156
157    /// General source consumer setup failure
158    pub const SOURCE_CONSUMER_SETUP_FAILED: ErrorCode = ErrorCode(10045);
159
160    /// Consumer creation failed
161    pub const CONSUMER_CREATE: ErrorCode = ErrorCode(10012);
162
163    /// Consumer expected to be durable but no durable name set in subject
164    pub const CONSUMER_DURABLE_NAME_NOT_IN_SUBJECT: ErrorCode = ErrorCode(10016);
165
166    /// Stream limits error
167    pub const STREAM_LIMITS: ErrorCode = ErrorCode(10053);
168
169    /// Replicas configuration can not be updated
170    pub const STREAM_REPLICAS_NOT_UPDATABLE: ErrorCode = ErrorCode(10061);
171
172    /// Template not found
173    pub const STREAM_TEMPLATE_NOT_FOUND: ErrorCode = ErrorCode(10068);
174
175    /// Jetstream cluster not assigned to this server
176    pub const CLUSTER_NOT_ASSIGNED: ErrorCode = ErrorCode(10007);
177
178    /// Jetstream cluster can't handle request
179    pub const CLUSTER_NOT_LEADER: ErrorCode = ErrorCode(10009);
180
181    /// Consumer name already in use
182    pub const CONSUMER_NAME_EXIST: ErrorCode = ErrorCode(10013);
183
184    /// Stream mirrors can't also contain other sources
185    pub const MIRROR_WITH_SOURCES: ErrorCode = ErrorCode(10031);
186
187    /// Stream not found
188    pub const STREAM_NOT_FOUND: ErrorCode = ErrorCode(10059);
189
190    /// Jetstream clustering support required
191    pub const CLUSTER_REQUIRED: ErrorCode = ErrorCode(10010);
192
193    /// Consumer expected to be durable but a durable name was not set
194    pub const CONSUMER_DURABLE_NAME_NOT_SET: ErrorCode = ErrorCode(10018);
195
196    /// Maximum number of streams reached
197    pub const MAXIMUM_STREAMS_LIMIT: ErrorCode = ErrorCode(10027);
198
199    /// Stream mirrors can not have both start seq and start time configured
200    pub const MIRROR_WITH_START_SEQUENCE_AND_TIME: ErrorCode = ErrorCode(10032);
201
202    /// Stream snapshot failed
203    pub const STREAM_SNAPSHOT: ErrorCode = ErrorCode(10064);
204
205    /// Stream update failed
206    pub const STREAM_UPDATE: ErrorCode = ErrorCode(10069);
207
208    /// Jetstream not in clustered mode
209    pub const CLUSTER_NOT_ACTIVE: ErrorCode = ErrorCode(10006);
210
211    /// Consumer name in subject does not match durable name in request
212    pub const CONSUMER_DURABLE_NAME_NOT_MATCH_SUBJECT: ErrorCode = ErrorCode(10017);
213
214    /// Insufficient memory resources available
215    pub const MEMORY_RESOURCES_EXCEEDED: ErrorCode = ErrorCode(10028);
216
217    /// Stream mirrors can not contain filtered subjects
218    pub const MIRROR_WITH_SUBJECT_FILTERS: ErrorCode = ErrorCode(10033);
219
220    /// Stream create failed with a string
221    pub const STREAM_CREATE: ErrorCode = ErrorCode(10049);
222
223    /// Server is not a member of the cluster
224    pub const CLUSTER_SERVER_NOT_MEMBER: ErrorCode = ErrorCode(10044);
225
226    /// No message found
227    pub const NO_MESSAGE_FOUND: ErrorCode = ErrorCode(10037);
228
229    /// Deliver subject not valid
230    pub const SNAPSHOT_DELIVER_SUBJECT_INVALID: ErrorCode = ErrorCode(10015);
231
232    /// General stream failure
233    pub const STREAM_GENERALOR: ErrorCode = ErrorCode(10051);
234
235    /// Invalid stream config
236    pub const STREAM_INVALID_CONFIG: ErrorCode = ErrorCode(10052);
237
238    /// Replicas > 1 not supported in non-clustered mode
239    pub const STREAM_REPLICAS_NOT_SUPPORTED: ErrorCode = ErrorCode(10074);
240
241    /// Stream message delete failed
242    pub const STREAM_MESSAGE_DELETE_FAILED: ErrorCode = ErrorCode(10057);
243
244    /// Peer remap failed
245    pub const PEER_REMAP: ErrorCode = ErrorCode(10075);
246
247    /// Stream store failed
248    pub const STREAM_STORE_FAILED: ErrorCode = ErrorCode(10077);
249
250    /// Consumer config required
251    pub const CONSUMER_CONFIG_REQUIRED: ErrorCode = ErrorCode(10078);
252
253    /// Consumer deliver subject has wildcards
254    pub const CONSUMER_DELIVER_TO_WILDCARDS: ErrorCode = ErrorCode(10079);
255
256    /// Consumer in push mode can not set max waiting
257    pub const CONSUMER_PUSH_MAX_WAITING: ErrorCode = ErrorCode(10080);
258
259    /// Consumer deliver subject forms a cycle
260    pub const CONSUMER_DELIVER_CYCLE: ErrorCode = ErrorCode(10081);
261
262    /// Consumer requires ack policy for max ack pending
263    pub const CONSUMER_MAX_PENDING_ACK_POLICY_REQUIRED: ErrorCode = ErrorCode(10082);
264
265    /// Consumer idle heartbeat needs to be >= 100ms
266    pub const CONSUMER_SMALL_HEARTBEAT: ErrorCode = ErrorCode(10083);
267
268    /// Consumer in pull mode requires ack policy
269    pub const CONSUMER_PULL_REQUIRES_ACK: ErrorCode = ErrorCode(10084);
270
271    /// Consumer in pull mode requires a durable name
272    pub const CONSUMER_PULL_NOT_DURABLE: ErrorCode = ErrorCode(10085);
273
274    /// Consumer in pull mode can not have rate limit set
275    pub const CONSUMER_PULL_WITH_RATE_LIMIT: ErrorCode = ErrorCode(10086);
276
277    /// Consumer max waiting needs to be positive
278    pub const CONSUMER_MAX_WAITING_NEGATIVE: ErrorCode = ErrorCode(10087);
279
280    /// Consumer idle heartbeat requires a push based consumer
281    pub const CONSUMER_HEARTBEAT_REQUIRES_PUSH: ErrorCode = ErrorCode(10088);
282
283    /// Consumer flow control requires a push based consumer
284    pub const CONSUMER_FLOW_CONTROL_REQUIRES_PUSH: ErrorCode = ErrorCode(10089);
285
286    /// Consumer direct requires a push based consumer
287    pub const CONSUMER_DIRECT_REQUIRES_PUSH: ErrorCode = ErrorCode(10090);
288
289    /// Consumer direct requires an ephemeral consumer
290    pub const CONSUMER_DIRECT_REQUIRES_EPHEMERAL: ErrorCode = ErrorCode(10091);
291
292    /// Consumer direct on a mapped consumer
293    pub const CONSUMER_ON_MAPPED: ErrorCode = ErrorCode(10092);
294
295    /// Consumer filter subject is not a valid subset of the interest subjects
296    pub const CONSUMER_FILTER_NOT_SUBSET: ErrorCode = ErrorCode(10093);
297
298    /// Invalid consumer policy
299    pub const CONSUMER_INVALID_POLICY: ErrorCode = ErrorCode(10094);
300
301    /// Failed to parse consumer sampling configuration
302    pub const CONSUMER_INVALID_SAMPLING: ErrorCode = ErrorCode(10095);
303
304    /// Stream not valid
305    pub const STREAM_INVALID: ErrorCode = ErrorCode(10096);
306
307    /// Workqueue stream requires explicit ack
308    pub const CONSUMER_WQ_REQUIRES_EXPLICIT_ACK: ErrorCode = ErrorCode(10098);
309
310    /// Multiple non-filtered consumers not allowed on workqueue stream
311    pub const CONSUMER_WQ_MULTIPLE_UNFILTERED: ErrorCode = ErrorCode(10099);
312
313    /// Filtered consumer not unique on workqueue stream
314    pub const CONSUMER_WQ_CONSUMER_NOT_UNIQUE: ErrorCode = ErrorCode(10100);
315
316    /// Consumer must be deliver all on workqueue stream
317    pub const CONSUMER_WQ_CONSUMER_NOT_DELIVER_ALL: ErrorCode = ErrorCode(10101);
318
319    /// Consumer name is too long
320    pub const CONSUMER_NAME_TOO_LONG: ErrorCode = ErrorCode(10102);
321
322    /// Durable name can not contain token separators and wildcards
323    pub const CONSUMER_BAD_DURABLE_NAME: ErrorCode = ErrorCode(10103);
324
325    /// Error creating store for consumer
326    pub const CONSUMER_STORE_FAILED: ErrorCode = ErrorCode(10104);
327
328    /// Consumer already exists and is still active
329    pub const CONSUMER_EXISTING_ACTIVE: ErrorCode = ErrorCode(10105);
330
331    /// Consumer replacement durable config not the same
332    pub const CONSUMER_REPLACEMENT_WITH_DIFFERENT_NAME: ErrorCode = ErrorCode(10106);
333
334    /// Consumer description is too long
335    pub const CONSUMER_DESCRIPTION_TOO_LONG: ErrorCode = ErrorCode(10107);
336
337    /// Header size exceeds maximum allowed of 64k
338    pub const STREAM_HEADER_EXCEEDS_MAXIMUM: ErrorCode = ErrorCode(10097);
339
340    /// Consumer with flow control also needs heartbeats
341    pub const CONSUMER_WITH_FLOW_CONTROL_NEEDS_HEARTBEATS: ErrorCode = ErrorCode(10108);
342
343    /// Invalid operation on sealed stream
344    pub const STREAM_SEALED: ErrorCode = ErrorCode(10109);
345
346    /// Stream purge failed
347    pub const STREAM_PURGE_FAILED: ErrorCode = ErrorCode(10110);
348
349    /// Stream rollup failed
350    pub const STREAM_ROLLUP_FAILED: ErrorCode = ErrorCode(10111);
351
352    /// Invalid push consumer deliver subject
353    pub const CONSUMER_INVALID_DELIVER_SUBJECT: ErrorCode = ErrorCode(10112);
354
355    /// Account requires a stream config to have max bytes set
356    pub const STREAM_MAX_BYTES_REQUIRED: ErrorCode = ErrorCode(10113);
357
358    /// Consumer max request batch needs to be > 0
359    pub const CONSUMER_MAX_REQUEST_BATCH_NEGATIVE: ErrorCode = ErrorCode(10114);
360
361    /// Consumer max request expires needs to be >= 1ms
362    pub const CONSUMER_MAX_REQUEST_EXPIRES_TO_SMALL: ErrorCode = ErrorCode(10115);
363
364    /// Max deliver is required to be > length of backoff values
365    pub const CONSUMER_MAX_DELIVER_BACKOFF: ErrorCode = ErrorCode(10116);
366
367    /// Subject details would exceed maximum allowed
368    pub const STREAM_INFO_MAX_SUBJECTS: ErrorCode = ErrorCode(10117);
369
370    /// Stream is offline
371    pub const STREAM_OFFLINE: ErrorCode = ErrorCode(10118);
372
373    /// Consumer is offline
374    pub const CONSUMER_OFFLINE: ErrorCode = ErrorCode(10119);
375
376    /// No jetstream default or applicable tiered limit present
377    pub const NO_LIMITS: ErrorCode = ErrorCode(10120);
378
379    /// Consumer max ack pending exceeds system limit
380    pub const CONSUMER_MAX_PENDING_ACK_EXCESS: ErrorCode = ErrorCode(10121);
381
382    /// Stream max bytes exceeds account limit max stream bytes
383    pub const STREAM_MAX_STREAM_BYTES_EXCEEDED: ErrorCode = ErrorCode(10122);
384
385    /// Can not move and scale a stream in a single update
386    pub const STREAM_MOVE_AND_SCALE: ErrorCode = ErrorCode(10123);
387
388    /// Stream move already in progress
389    pub const STREAM_MOVE_IN_PROGRESS: ErrorCode = ErrorCode(10124);
390
391    /// Consumer max request batch exceeds server limit
392    pub const CONSUMER_MAX_REQUEST_BATCH_EXCEEDED: ErrorCode = ErrorCode(10125);
393
394    /// Consumer config replica count exceeds parent stream
395    pub const CONSUMER_REPLICAS_EXCEEDS_STREAM: ErrorCode = ErrorCode(10126);
396
397    /// Consumer name can not contain path separators
398    pub const CONSUMER_NAME_CONTAINS_PATH_SEPARATORS: ErrorCode = ErrorCode(10127);
399
400    /// Stream name can not contain path separators
401    pub const STREAM_NAME_CONTAINS_PATH_SEPARATORS: ErrorCode = ErrorCode(10128);
402
403    /// Stream move not in progress
404    pub const STREAM_MOVE_NOT_IN_PROGRESS: ErrorCode = ErrorCode(10129);
405
406    /// Stream name already in use, cannot restore
407    pub const STREAM_NAME_EXIST_RESTORE_FAILED: ErrorCode = ErrorCode(10130);
408
409    /// Consumer create request did not match filtered subject from create subject
410    pub const CONSUMER_CREATE_FILTER_SUBJECT_MISMATCH: ErrorCode = ErrorCode(10131);
411
412    /// Consumer durable and name have to be equal if both are provided
413    pub const CONSUMER_CREATE_DURABLE_AND_NAME_MISMATCH: ErrorCode = ErrorCode(10132);
414
415    /// Replicas count cannot be negative
416    pub const REPLICAS_COUNT_CANNOT_BE_NEGATIVE: ErrorCode = ErrorCode(10133);
417
418    /// Consumer config replicas must match interest retention stream's replicas
419    pub const CONSUMER_REPLICAS_SHOULD_MATCH_STREAM: ErrorCode = ErrorCode(10134);
420
421    /// Consumer metadata exceeds maximum size
422    pub const CONSUMER_METADATA_LENGTH: ErrorCode = ErrorCode(10135);
423
424    /// Consumer cannot have both filter_subject and filter_subjects specified
425    pub const CONSUMER_DUPLICATE_FILTER_SUBJECTS: ErrorCode = ErrorCode(10136);
426
427    /// Consumer with multiple subject filters cannot use subject based api
428    pub const CONSUMER_MULTIPLE_FILTERS_NOT_ALLOWED: ErrorCode = ErrorCode(10137);
429
430    /// Consumer subject filters cannot overlap
431    pub const CONSUMER_OVERLAPPING_SUBJECT_FILTERS: ErrorCode = ErrorCode(10138);
432
433    /// Consumer filter in filter_subjects cannot be empty
434    pub const CONSUMER_EMPTY_FILTER: ErrorCode = ErrorCode(10139);
435
436    /// Duplicate source configuration detected
437    pub const SOURCE_DUPLICATE_DETECTED: ErrorCode = ErrorCode(10140);
438
439    /// Sourced stream name is invalid
440    pub const SOURCE_INVALID_STREAM_NAME: ErrorCode = ErrorCode(10141);
441
442    /// Mirrored stream name is invalid
443    pub const MIRROR_INVALID_STREAM_NAME: ErrorCode = ErrorCode(10142);
444
445    /// Source with multiple subject transforms cannot also have a single subject filter
446    pub const SOURCE_MULTIPLE_FILTERS_NOT_ALLOWED: ErrorCode = ErrorCode(10144);
447
448    /// Source subject filter is invalid
449    pub const SOURCE_INVALID_SUBJECT_FILTER: ErrorCode = ErrorCode(10145);
450
451    /// Source transform destination is invalid
452    pub const SOURCE_INVALID_TRANSFORM_DESTINATION: ErrorCode = ErrorCode(10146);
453
454    /// Source filters cannot overlap
455    pub const SOURCE_OVERLAPPING_SUBJECT_FILTERS: ErrorCode = ErrorCode(10147);
456
457    /// Consumer already exists
458    pub const CONSUMER_ALREADY_EXISTS: ErrorCode = ErrorCode(10148);
459
460    /// Consumer does not exist
461    pub const CONSUMER_DOES_NOT_EXIST: ErrorCode = ErrorCode(10149);
462
463    /// Mirror with multiple subject transforms cannot also have a single subject filter
464    pub const MIRROR_MULTIPLE_FILTERS_NOT_ALLOWED: ErrorCode = ErrorCode(10150);
465
466    /// Mirror subject filter is invalid
467    pub const MIRROR_INVALID_SUBJECT_FILTER: ErrorCode = ErrorCode(10151);
468
469    /// Mirror subject filters cannot overlap
470    pub const MIRROR_OVERLAPPING_SUBJECT_FILTERS: ErrorCode = ErrorCode(10152);
471
472    /// Consumer inactive threshold exceeds system limit
473    pub const CONSUMER_INACTIVE_THRESHOLD_EXCESS: ErrorCode = ErrorCode(10153);
474}
475
476/// `Error` type returned from an API response when an error occurs.
477#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
478pub struct Error {
479    code: usize,
480    err_code: ErrorCode,
481    description: Option<String>,
482}
483
484impl Error {
485    /// Returns the status code associated with this error
486    pub fn code(&self) -> usize {
487        self.code
488    }
489
490    /// Returns the server side error code associated with this error.
491    pub fn error_code(&self) -> ErrorCode {
492        self.err_code
493    }
494
495    pub fn kind(&self) -> ErrorCode {
496        self.err_code
497    }
498}
499
500impl fmt::Display for Error {
501    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
502        write!(
503            fmt,
504            "{} (code {}, error code {})",
505            self.description.as_ref().unwrap_or(&"unknown".to_string()),
506            self.code,
507            self.err_code.0,
508        )
509    }
510}
511
512impl error::Error for Error {}