1use crate::{
19 schema::{Name, Schema, SchemaKind, UnionSchema},
20 types::{Value, ValueKind},
21};
22use std::{error::Error as _, fmt};
23
24#[derive(thiserror::Error, Debug)]
31#[repr(transparent)]
32#[error(transparent)]
33pub struct Error {
34 details: Box<Details>,
35}
36
37impl Error {
38 pub fn new(details: Details) -> Self {
39 Self {
40 details: Box::new(details),
41 }
42 }
43
44 pub fn details(&self) -> &Details {
45 &self.details
46 }
47
48 pub fn into_details(self) -> Details {
49 *self.details
50 }
51}
52
53impl From<Details> for Error {
54 fn from(details: Details) -> Self {
55 Self::new(details)
56 }
57}
58
59impl serde::ser::Error for Error {
60 fn custom<T: fmt::Display>(msg: T) -> Self {
61 Self::new(<Details as serde::ser::Error>::custom(msg))
62 }
63}
64
65impl serde::de::Error for Error {
66 fn custom<T: fmt::Display>(msg: T) -> Self {
67 Self::new(<Details as serde::de::Error>::custom(msg))
68 }
69}
70
71#[derive(thiserror::Error)]
72pub enum Details {
73 #[error("Bad Snappy CRC32; expected {expected:x} but got {actual:x}")]
74 SnappyCrc32 { expected: u32, actual: u32 },
75
76 #[error("Invalid u8 for bool: {0}")]
77 BoolValue(u8),
78
79 #[error("Not a fixed value, required for decimal with fixed schema: {0:?}")]
80 FixedValue(Value),
81
82 #[error("Not a bytes value, required for decimal with bytes schema: {0:?}")]
83 BytesValue(Value),
84
85 #[error("Not a string value, required for uuid: {0:?}")]
86 GetUuidFromStringValue(Value),
87
88 #[error("Two schemas with the same fullname were given: {0:?}")]
89 NameCollision(String),
90
91 #[error("Not a fixed or bytes type, required for decimal schema, got: {0:?}")]
92 ResolveDecimalSchema(SchemaKind),
93
94 #[error("Invalid utf-8 string")]
95 ConvertToUtf8(#[source] std::string::FromUtf8Error),
96
97 #[error("Invalid utf-8 string")]
98 ConvertToUtf8Error(#[source] std::str::Utf8Error),
99
100 #[error("Value does not match schema")]
102 Validation,
103
104 #[error("Value {value:?} does not match schema {schema:?}: Reason: {reason}")]
106 ValidationWithReason {
107 value: Value,
108 schema: Schema,
109 reason: String,
110 },
111
112 #[error("Unable to allocate {desired} bytes (maximum allowed: {maximum})")]
113 MemoryAllocation { desired: usize, maximum: usize },
114
115 #[error(
117 "Number of bytes requested for decimal sign extension {requested} is less than the number of bytes needed to decode {needed}"
118 )]
119 SignExtend { requested: usize, needed: usize },
120
121 #[error("Failed to read boolean bytes: {0}")]
122 ReadBoolean(#[source] std::io::Error),
123
124 #[error("Failed to read bytes: {0}")]
125 ReadBytes(#[source] std::io::Error),
126
127 #[error("Failed to read string: {0}")]
128 ReadString(#[source] std::io::Error),
129
130 #[error("Failed to read double: {0}")]
131 ReadDouble(#[source] std::io::Error),
132
133 #[error("Failed to read float: {0}")]
134 ReadFloat(#[source] std::io::Error),
135
136 #[error("Failed to read duration: {0}")]
137 ReadDuration(#[source] std::io::Error),
138
139 #[error("Failed to read fixed number of bytes '{1}': : {0}")]
140 ReadFixed(#[source] std::io::Error, usize),
141
142 #[error("Failed to convert &str to UUID: {0}")]
143 ConvertStrToUuid(#[source] uuid::Error),
144
145 #[error("Failed to convert Fixed bytes to UUID. It must be exactly 16 bytes, got {0}")]
146 ConvertFixedToUuid(usize),
147
148 #[error("Failed to convert Fixed bytes to UUID: {0}")]
149 ConvertSliceToUuid(#[source] uuid::Error),
150
151 #[error("Map key is not a string; key type is {0:?}")]
152 MapKeyType(ValueKind),
153
154 #[error("Union index {index} out of bounds: {num_variants}")]
155 GetUnionVariant { index: i64, num_variants: usize },
156
157 #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")]
158 #[error("Enum symbol index out of bounds: {num_variants}")]
159 EnumSymbolIndex { index: usize, num_variants: usize },
160
161 #[error("Enum symbol not found {0}")]
162 GetEnumSymbol(String),
163
164 #[error("Unable to decode enum index")]
165 GetEnumUnknownIndexValue,
166
167 #[error("Scale {scale} is greater than precision {precision}")]
168 GetScaleAndPrecision { scale: usize, precision: usize },
169
170 #[error(
171 "Fixed type number of bytes {size} is not large enough to hold decimal values of precision {precision}"
172 )]
173 GetScaleWithFixedSize { size: usize, precision: usize },
174
175 #[error("Expected Value::Uuid, got: {0:?}")]
176 GetUuid(Value),
177
178 #[error("Expected Value::BigDecimal, got: {0:?}")]
179 GetBigDecimal(Value),
180
181 #[error("Fixed bytes of size 12 expected, got Fixed of size {0}")]
182 GetDecimalFixedBytes(usize),
183
184 #[error("Expected Value::Duration or Value::Fixed(12), got: {0:?}")]
185 ResolveDuration(Value),
186
187 #[error("Expected Value::Decimal, Value::Bytes or Value::Fixed, got: {0:?}")]
188 ResolveDecimal(Value),
189
190 #[error("Missing field in record: {0:?}")]
191 GetField(String),
192
193 #[error("Unable to convert to u8, got {0:?}")]
194 GetU8(Value),
195
196 #[error("Precision {precision} too small to hold decimal values with {num_bytes} bytes")]
197 ComparePrecisionAndSize { precision: usize, num_bytes: usize },
198
199 #[error("Cannot convert length to i32: {1}")]
200 ConvertLengthToI32(#[source] std::num::TryFromIntError, usize),
201
202 #[error("Expected Value::Date or Value::Int, got: {0:?}")]
203 GetDate(Value),
204
205 #[error("Expected Value::TimeMillis or Value::Int, got: {0:?}")]
206 GetTimeMillis(Value),
207
208 #[error("Expected Value::TimeMicros, Value::Long or Value::Int, got: {0:?}")]
209 GetTimeMicros(Value),
210
211 #[error("Expected Value::TimestampMillis, Value::Long or Value::Int, got: {0:?}")]
212 GetTimestampMillis(Value),
213
214 #[error("Expected Value::TimestampMicros, Value::Long or Value::Int, got: {0:?}")]
215 GetTimestampMicros(Value),
216
217 #[error("Expected Value::TimestampNanos, Value::Long or Value::Int, got: {0:?}")]
218 GetTimestampNanos(Value),
219
220 #[error("Expected Value::LocalTimestampMillis, Value::Long or Value::Int, got: {0:?}")]
221 GetLocalTimestampMillis(Value),
222
223 #[error("Expected Value::LocalTimestampMicros, Value::Long or Value::Int, got: {0:?}")]
224 GetLocalTimestampMicros(Value),
225
226 #[error("Expected Value::LocalTimestampNanos, Value::Long or Value::Int, got: {0:?}")]
227 GetLocalTimestampNanos(Value),
228
229 #[error("Expected Value::Null, got: {0:?}")]
230 GetNull(Value),
231
232 #[error("Expected Value::Boolean, got: {0:?}")]
233 GetBoolean(Value),
234
235 #[error("Expected Value::Int, got: {0:?}")]
236 GetInt(Value),
237
238 #[error("Expected Value::Long or Value::Int, got: {0:?}")]
239 GetLong(Value),
240
241 #[error(r#"Expected Value::Double, Value::Float, Value::Int, Value::Long or Value::String ("NaN", "INF", "Infinity", "-INF" or "-Infinity"), got: {0:?}"#)]
242 GetDouble(Value),
243
244 #[error(r#"Expected Value::Float, Value::Double, Value::Int, Value::Long or Value::String ("NaN", "INF", "Infinity", "-INF" or "-Infinity"), got: {0:?}"#)]
245 GetFloat(Value),
246
247 #[error("Expected Value::Bytes, got: {0:?}")]
248 GetBytes(Value),
249
250 #[error("Expected Value::String, Value::Bytes or Value::Fixed, got: {0:?}")]
251 GetString(Value),
252
253 #[error("Expected Value::Enum, got: {0:?}")]
254 GetEnum(Value),
255
256 #[error("Fixed size mismatch, expected: {size}, got: {n}")]
257 CompareFixedSizes { size: usize, n: usize },
258
259 #[error("String expected for fixed, got: {0:?}")]
260 GetStringForFixed(Value),
261
262 #[error("Enum default {symbol:?} is not among allowed symbols {symbols:?}")]
263 GetEnumDefault {
264 symbol: String,
265 symbols: Vec<String>,
266 },
267
268 #[error("Enum value index {index} is out of bounds {nsymbols}")]
269 GetEnumValue { index: usize, nsymbols: usize },
270
271 #[error("Key {0} not found in decimal metadata JSON")]
272 GetDecimalMetadataFromJson(&'static str),
273
274 #[error("Could not find matching type in {schema:?} for {value:?}")]
275 FindUnionVariant { schema: UnionSchema, value: Value },
276
277 #[error("Union type should not be empty")]
278 EmptyUnion,
279
280 #[error("Array({expected:?}) expected, got {other:?}")]
281 GetArray { expected: SchemaKind, other: Value },
282
283 #[error("Map({expected:?}) expected, got {other:?}")]
284 GetMap { expected: SchemaKind, other: Value },
285
286 #[error("Record with fields {expected:?} expected, got {other:?}")]
287 GetRecord {
288 expected: Vec<(String, SchemaKind)>,
289 other: Value,
290 },
291
292 #[error("No `name` field")]
293 GetNameField,
294
295 #[error("No `name` in record field")]
296 GetNameFieldFromRecord,
297
298 #[error("Unions may not directly contain a union")]
299 GetNestedUnion,
300
301 #[error("Unions cannot contain duplicate types")]
302 GetUnionDuplicate,
303
304 #[error("One union type {0:?} must match the `default`'s value type {1:?}")]
305 GetDefaultUnion(SchemaKind, ValueKind),
306
307 #[error("`default`'s value type of field {0:?} in {1:?} must be {2:?}")]
308 GetDefaultRecordField(String, String, String),
309
310 #[error("JSON value {0} claims to be u64 but cannot be converted")]
311 GetU64FromJson(serde_json::Number),
312
313 #[error("JSON value {0} claims to be i64 but cannot be converted")]
314 GetI64FromJson(serde_json::Number),
315
316 #[error("Cannot convert u64 to usize: {1}")]
317 ConvertU64ToUsize(#[source] std::num::TryFromIntError, u64),
318
319 #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")]
320 #[error("Cannot convert u32 to usize: {1}")]
321 ConvertU32ToUsize(#[source] std::num::TryFromIntError, u32),
322
323 #[error("Cannot convert i64 to usize: {1}")]
324 ConvertI64ToUsize(#[source] std::num::TryFromIntError, i64),
325
326 #[error("Cannot convert i32 to usize: {1}")]
327 ConvertI32ToUsize(#[source] std::num::TryFromIntError, i32),
328
329 #[error("Invalid JSON value for decimal precision/scale integer: {0}")]
330 GetPrecisionOrScaleFromJson(serde_json::Number),
331
332 #[error("Failed to parse schema from JSON")]
333 ParseSchemaJson(#[source] serde_json::Error),
334
335 #[error("Failed to read schema")]
336 ReadSchemaFromReader(#[source] std::io::Error),
337
338 #[error("Must be a JSON string, object or array")]
339 ParseSchemaFromValidJson,
340
341 #[error("Unknown primitive type: {0}")]
342 ParsePrimitive(String),
343
344 #[error("invalid JSON for {key:?}: {value:?}")]
345 GetDecimalMetadataValueFromJson {
346 key: String,
347 value: serde_json::Value,
348 },
349
350 #[error("The decimal precision ({precision}) must be bigger or equal to the scale ({scale})")]
351 DecimalPrecisionLessThanScale { precision: usize, scale: usize },
352
353 #[error("The decimal precision ({precision}) must be a positive number")]
354 DecimalPrecisionMuBePositive { precision: usize },
355
356 #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")]
357 #[error("Unreadable big decimal sign")]
358 BigDecimalSign,
359
360 #[error("Unreadable length for big decimal inner bytes: {0}")]
361 BigDecimalLen(#[source] Box<Error>),
362
363 #[error("Unreadable big decimal scale")]
364 BigDecimalScale,
365
366 #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")]
367 #[error("Unexpected `type` {0} variant for `logicalType`")]
368 GetLogicalTypeVariant(serde_json::Value),
369
370 #[error("No `type` field found for `logicalType`")]
371 GetLogicalTypeField,
372
373 #[error("logicalType must be a string, but is {0:?}")]
374 GetLogicalTypeFieldType(serde_json::Value),
375
376 #[error("Unknown complex type: {0}")]
377 GetComplexType(serde_json::Value),
378
379 #[error("No `type` in complex type")]
380 GetComplexTypeField,
381
382 #[error("No `fields` in record")]
383 GetRecordFieldsJson,
384
385 #[error("No `symbols` field in enum")]
386 GetEnumSymbolsField,
387
388 #[error("Unable to parse `symbols` in enum")]
389 GetEnumSymbols,
390
391 #[error("Invalid enum symbol name {0}")]
392 EnumSymbolName(String),
393
394 #[error("Invalid field name {0}")]
395 FieldName(String),
396
397 #[error("Duplicate field name {0}")]
398 FieldNameDuplicate(String),
399
400 #[error("Invalid schema name {0}. It must match the regex '{1}'")]
401 InvalidSchemaName(String, &'static str),
402
403 #[error("Invalid namespace {0}. It must match the regex '{1}'")]
404 InvalidNamespace(String, &'static str),
405
406 #[error(
407 "Invalid schema: There is no type called '{0}', if you meant to define a non-primitive schema, it should be defined inside `type` attribute. Please review the specification"
408 )]
409 InvalidSchemaRecord(String),
410
411 #[error("Duplicate enum symbol {0}")]
412 EnumSymbolDuplicate(String),
413
414 #[error("Default value for enum must be a string! Got: {0}")]
415 EnumDefaultWrongType(serde_json::Value),
416
417 #[error("No `items` in array")]
418 GetArrayItemsField,
419
420 #[error("No `values` in map")]
421 GetMapValuesField,
422
423 #[error("Fixed schema `size` value must be a positive integer: {0}")]
424 GetFixedSizeFieldPositive(serde_json::Value),
425
426 #[error("Fixed schema has no `size`")]
427 GetFixedSizeField,
428
429 #[error("Fixed schema's default value length ({0}) does not match its size ({1})")]
430 FixedDefaultLenSizeMismatch(usize, u64),
431
432 #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")]
433 #[error("Failed to compress with flate: {0}")]
434 DeflateCompress(#[source] std::io::Error),
435
436 #[deprecated(since = "0.19.0", note = "This error can no longer occur")]
438 #[error("Failed to finish flate compressor: {0}")]
439 DeflateCompressFinish(#[source] std::io::Error),
440
441 #[error("Failed to decompress with flate: {0}")]
442 DeflateDecompress(#[source] std::io::Error),
443
444 #[cfg(feature = "snappy")]
445 #[error("Failed to compress with snappy: {0}")]
446 SnappyCompress(#[source] snap::Error),
447
448 #[cfg(feature = "snappy")]
449 #[error("Failed to get snappy decompression length: {0}")]
450 GetSnappyDecompressLen(#[source] snap::Error),
451
452 #[cfg(feature = "snappy")]
453 #[error("Failed to decompress with snappy: {0}")]
454 SnappyDecompress(#[source] snap::Error),
455
456 #[error("Failed to compress with zstd: {0}")]
457 ZstdCompress(#[source] std::io::Error),
458
459 #[error("Failed to decompress with zstd: {0}")]
460 ZstdDecompress(#[source] std::io::Error),
461
462 #[error("Failed to read header: {0}")]
463 ReadHeader(#[source] std::io::Error),
464
465 #[error("wrong magic in header")]
466 HeaderMagic,
467
468 #[error("Message Header mismatch. Expected: {0:?}. Actual: {1:?}")]
469 SingleObjectHeaderMismatch(Vec<u8>, Vec<u8>),
470
471 #[error("Failed to get JSON from avro.schema key in map")]
472 GetAvroSchemaFromMap,
473
474 #[error("no metadata in header")]
475 GetHeaderMetadata,
476
477 #[error("Failed to read marker bytes: {0}")]
478 ReadMarker(#[source] std::io::Error),
479
480 #[error("Failed to read block marker bytes: {0}")]
481 ReadBlockMarker(#[source] std::io::Error),
482
483 #[error("Read into buffer failed: {0}")]
484 ReadIntoBuf(#[source] std::io::Error),
485
486 #[error("block marker does not match header marker")]
487 GetBlockMarker,
488
489 #[error("Overflow when decoding integer value")]
490 IntegerOverflow,
491
492 #[error("Failed to read bytes for decoding variable length integer: {0}")]
493 ReadVariableIntegerBytes(#[source] std::io::Error),
494
495 #[error("Decoded integer out of range for i32: {1}: {0}")]
496 ZagI32(#[source] std::num::TryFromIntError, i64),
497
498 #[error("unable to read block")]
499 ReadBlock,
500
501 #[error("Failed to serialize value into Avro value: {0}")]
502 SerializeValue(String),
503
504 #[error("Failed to serialize value of type {value_type} using schema {schema:?}: {value}")]
505 SerializeValueWithSchema {
506 value_type: &'static str,
507 value: String,
508 schema: Schema,
509 },
510
511 #[error("Failed to serialize field '{field_name}' for record {record_schema:?}: {error}")]
512 SerializeRecordFieldWithSchema {
513 field_name: &'static str,
514 record_schema: Schema,
515 error: Box<Error>,
516 },
517
518 #[error("Failed to deserialize Avro value into value: {0}")]
519 DeserializeValue(String),
520
521 #[error("Failed to write buffer bytes during flush: {0}")]
522 WriteBytes(#[source] std::io::Error),
523
524 #[error("Failed to flush inner writer during flush: {0}")]
525 FlushWriter(#[source] std::io::Error),
526
527 #[error("Failed to write marker: {0}")]
528 WriteMarker(#[source] std::io::Error),
529
530 #[error("Failed to convert JSON to string: {0}")]
531 ConvertJsonToString(#[source] serde_json::Error),
532
533 #[error("failed to convert avro float to json: {0}")]
535 ConvertF64ToJson(f64),
536
537 #[error("Unresolved schema reference: {0}")]
539 SchemaResolutionError(Name),
540
541 #[error("The file metadata is already flushed.")]
542 FileHeaderAlreadyWritten,
543
544 #[error("Metadata keys starting with 'avro.' are reserved for internal usage: {0}.")]
545 InvalidMetadataKey(String),
546
547 #[error("Two named schema defined for same fullname: {0}.")]
549 AmbiguousSchemaDefinition(Name),
550
551 #[error("Signed decimal bytes length {0} not equal to fixed schema size {1}.")]
552 EncodeDecimalAsFixedError(usize, usize),
553
554 #[error("There is no entry for '{0}' in the lookup table: {1}.")]
555 NoEntryInLookupTable(String, String),
556
557 #[error("Can only encode value type {value_kind:?} as one of {supported_schema:?}")]
558 EncodeValueAsSchemaError {
559 value_kind: ValueKind,
560 supported_schema: Vec<SchemaKind>,
561 },
562 #[error("Internal buffer not drained properly. Re-initialize the single object writer struct!")]
563 IllegalSingleObjectWriterState,
564
565 #[error("Codec '{0}' is not supported/enabled")]
566 CodecNotSupported(String),
567
568 #[error("Invalid Avro data! Cannot read codec type from value that is not Value::Bytes.")]
569 BadCodecMetadata,
570
571 #[error("Cannot convert a slice to Uuid: {0}")]
572 UuidFromSlice(#[source] uuid::Error),
573}
574
575#[derive(thiserror::Error, PartialEq)]
576pub enum CompatibilityError {
577 #[error(
578 "Incompatible schema types! Writer schema is '{writer_schema_type}', but reader schema is '{reader_schema_type}'"
579 )]
580 WrongType {
581 writer_schema_type: String,
582 reader_schema_type: String,
583 },
584
585 #[error("Incompatible schema types! The {schema_type} should have been {expected_type:?}")]
586 TypeExpected {
587 schema_type: String,
588 expected_type: Vec<SchemaKind>,
589 },
590
591 #[error(
592 "Incompatible schemata! Field '{0}' in reader schema does not match the type in the writer schema"
593 )]
594 FieldTypeMismatch(String, #[source] Box<CompatibilityError>),
595
596 #[error("Incompatible schemata! Field '{0}' in reader schema must have a default value")]
597 MissingDefaultValue(String),
598
599 #[error("Incompatible schemata! Reader's symbols must contain all writer's symbols")]
600 MissingSymbols,
601
602 #[error("Incompatible schemata! All elements in union must match for both schemas")]
603 MissingUnionElements,
604
605 #[error("Incompatible schemata! Name and size don't match for fixed")]
606 FixedMismatch,
607
608 #[error(
609 "Incompatible schemata! The name must be the same for both schemas. Writer's name {writer_name} and reader's name {reader_name}"
610 )]
611 NameMismatch {
612 writer_name: String,
613 reader_name: String,
614 },
615
616 #[error(
617 "Incompatible schemata! Unknown type for '{0}'. Make sure that the type is a valid one"
618 )]
619 Inconclusive(String),
620}
621
622impl serde::ser::Error for Details {
623 fn custom<T: fmt::Display>(msg: T) -> Self {
624 Details::SerializeValue(msg.to_string())
625 }
626}
627
628impl serde::de::Error for Details {
629 fn custom<T: fmt::Display>(msg: T) -> Self {
630 Details::DeserializeValue(msg.to_string())
631 }
632}
633
634impl fmt::Debug for Details {
635 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
636 let mut msg = self.to_string();
637 if let Some(e) = self.source() {
638 msg.extend([": ", &e.to_string()]);
639 }
640 write!(f, "{msg}")
641 }
642}
643
644impl fmt::Debug for CompatibilityError {
645 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
646 let mut msg = self.to_string();
647 if let Some(e) = self.source() {
648 msg.extend([": ", &e.to_string()]);
649 }
650 write!(f, "{msg}")
651 }
652}