Skip to main content

apache_avro/
error.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use std::{error::Error as _, fmt};
19
20use crate::{
21    schema::{Name, RecordSchema, Schema, SchemaKind, UnionSchema},
22    types::{Value, ValueKind},
23};
24
25/// Errors encountered by Avro.
26///
27/// To inspect the details of the error use [`details`](Self::details) or [`into_details`](Self::into_details)
28/// to get a [`Details`] which contains more precise error information.
29///
30/// See [`Details`] for all possible errors.
31#[derive(thiserror::Error, Debug)]
32#[repr(transparent)]
33#[error(transparent)]
34pub struct Error {
35    details: Box<Details>,
36}
37
38impl Error {
39    pub fn new(details: Details) -> Self {
40        Self {
41            details: Box::new(details),
42        }
43    }
44
45    pub fn details(&self) -> &Details {
46        &self.details
47    }
48
49    pub fn into_details(self) -> Details {
50        *self.details
51    }
52}
53
54impl From<Details> for Error {
55    fn from(details: Details) -> Self {
56        Self::new(details)
57    }
58}
59
60impl serde::ser::Error for Error {
61    fn custom<T: fmt::Display>(msg: T) -> Self {
62        Self::new(<Details as serde::ser::Error>::custom(msg))
63    }
64}
65
66impl serde::de::Error for Error {
67    fn custom<T: fmt::Display>(msg: T) -> Self {
68        Self::new(<Details as serde::de::Error>::custom(msg))
69    }
70}
71
72#[derive(thiserror::Error)]
73pub enum Details {
74    #[error("Bad Snappy CRC32; expected {expected:x} but got {actual:x}")]
75    SnappyCrc32 { expected: u32, actual: u32 },
76
77    #[error("Invalid u8 for bool: {0}")]
78    BoolValue(u8),
79
80    #[error("Not a fixed value, required for decimal with fixed schema: {0:?}")]
81    FixedValue(Value),
82
83    #[error("Not a bytes value, required for decimal with bytes schema: {0:?}")]
84    BytesValue(Value),
85
86    #[error("Not a string value, required for uuid: {0:?}")]
87    GetUuidFromStringValue(Value),
88
89    #[error("Two schemas with the same fullname were given: {0:?}")]
90    NameCollision(String),
91
92    #[error("Not a fixed or bytes type, required for decimal schema, got: {0:?}")]
93    ResolveDecimalSchema(SchemaKind),
94
95    #[error("Invalid utf-8 string")]
96    ConvertToUtf8(#[source] std::string::FromUtf8Error),
97
98    #[error("Invalid utf-8 string")]
99    ConvertToUtf8Error(#[source] std::str::Utf8Error),
100
101    /// Describes errors happened while validating Avro data.
102    #[error("Value does not match schema")]
103    Validation,
104
105    /// Describes errors happened while validating Avro data.
106    #[error("Value {value:?} does not match schema {schema:?}: Reason: {reason}")]
107    ValidationWithReason {
108        value: Value,
109        schema: Schema,
110        reason: String,
111    },
112
113    #[error(
114        "{} (maximum allowed: {maximum}). Change the limit using `apache_avro::util::max_allocation_bytes`",
115        if let Some(desired) = desired {
116            format!("Unable to allocate {desired} bytes")
117        } else {
118            "Allocation limit reached with unknown amount of bytes remaining".to_string()
119        },
120    )]
121    MemoryAllocation {
122        desired: Option<usize>,
123        maximum: usize,
124    },
125
126    /// Describe a specific error happening with decimal representation
127    #[error(
128        "Number of bytes requested for decimal sign extension {requested} is less than the number of bytes needed to decode {needed}"
129    )]
130    SignExtend { requested: usize, needed: usize },
131
132    #[error("Failed to read boolean bytes: {0}")]
133    ReadBoolean(#[source] std::io::Error),
134
135    #[error("Failed to read bytes: {0}")]
136    ReadBytes(#[source] std::io::Error),
137
138    #[error("Failed to read string: {0}")]
139    ReadString(#[source] std::io::Error),
140
141    #[error("Failed to read double: {0}")]
142    ReadDouble(#[source] std::io::Error),
143
144    #[error("Failed to read float: {0}")]
145    ReadFloat(#[source] std::io::Error),
146
147    #[error("Failed to read duration: {0}")]
148    ReadDuration(#[source] std::io::Error),
149
150    #[error("Failed to read fixed number of bytes '{1}': : {0}")]
151    ReadFixed(#[source] std::io::Error, usize),
152
153    #[error("Failed to convert &str to UUID: {0}")]
154    ConvertStrToUuid(#[source] uuid::Error),
155
156    #[error("Failed to convert Fixed bytes to UUID. It must be exactly 16 bytes, got {0}")]
157    ConvertFixedToUuid(usize),
158
159    #[error("Failed to convert Fixed bytes to UUID: {0}")]
160    ConvertSliceToUuid(#[source] uuid::Error),
161
162    #[error("Map key is not a string; key type is {0:?}")]
163    MapKeyType(ValueKind),
164
165    #[error("Union index {index} out of bounds: {num_variants}")]
166    GetUnionVariant { index: i64, num_variants: usize },
167
168    #[error(
169        "Enum symbol index out of bounds: got {index} but there are only {num_variants} variants"
170    )]
171    EnumSymbolIndex { index: usize, num_variants: usize },
172
173    #[error("Enum symbol not found {0}")]
174    GetEnumSymbol(String),
175
176    #[error("Unable to decode enum index")]
177    GetEnumUnknownIndexValue,
178
179    #[error("Scale {scale} is greater than precision {precision}")]
180    GetScaleAndPrecision { scale: usize, precision: usize },
181
182    #[error(
183        "Fixed type number of bytes {size} is not large enough to hold decimal values of precision {precision}"
184    )]
185    GetScaleWithFixedSize { size: usize, precision: usize },
186
187    #[error("Expected Value::Uuid, got: {0:?}")]
188    GetUuid(Value),
189
190    #[error("Expected Value::BigDecimal, got: {0:?}")]
191    GetBigDecimal(Value),
192
193    #[error("Fixed bytes of size 12 expected, got Fixed of size {0}")]
194    GetDurationFixedBytes(usize),
195
196    #[error("Expected Value::Duration or Value::Fixed(12), got: {0:?}")]
197    ResolveDuration(Value),
198
199    #[error("Expected Value::Decimal, Value::Bytes, Value::Fixed or Value::String, got: {0:?}")]
200    ResolveDecimal(Value),
201
202    #[error("Missing field in record: {0:?}")]
203    GetField(String),
204
205    #[error("Unable to convert to u8, got {0:?}")]
206    GetU8(Value),
207
208    #[error("Precision {precision} too small to hold decimal values with {num_bytes} bytes")]
209    ComparePrecisionAndSize { precision: usize, num_bytes: usize },
210
211    #[error("Cannot convert length to i32: {1}")]
212    ConvertLengthToI32(#[source] std::num::TryFromIntError, usize),
213
214    #[error("Expected Value::Date or Value::Int, got: {0:?}")]
215    GetDate(Value),
216
217    #[error("Expected Value::TimeMillis or Value::Int, got: {0:?}")]
218    GetTimeMillis(Value),
219
220    #[error("Expected Value::TimeMicros, Value::Long or Value::Int, got: {0:?}")]
221    GetTimeMicros(Value),
222
223    #[error("Expected Value::TimestampMillis, Value::Long or Value::Int, got: {0:?}")]
224    GetTimestampMillis(Value),
225
226    #[error("Expected Value::TimestampMicros, Value::Long or Value::Int, got: {0:?}")]
227    GetTimestampMicros(Value),
228
229    #[error("Expected Value::TimestampNanos, Value::Long or Value::Int, got: {0:?}")]
230    GetTimestampNanos(Value),
231
232    #[error("Expected Value::LocalTimestampMillis, Value::Long or Value::Int, got: {0:?}")]
233    GetLocalTimestampMillis(Value),
234
235    #[error("Expected Value::LocalTimestampMicros, Value::Long or Value::Int, got: {0:?}")]
236    GetLocalTimestampMicros(Value),
237
238    #[error("Expected Value::LocalTimestampNanos, Value::Long or Value::Int, got: {0:?}")]
239    GetLocalTimestampNanos(Value),
240
241    #[error("Expected Value::Null, got: {0:?}")]
242    GetNull(Value),
243
244    #[error("Expected Value::Boolean, got: {0:?}")]
245    GetBoolean(Value),
246
247    #[error("Expected Value::Int, got: {0:?}")]
248    GetInt(Value),
249
250    #[error("Expected Value::Long or Value::Int, got: {0:?}")]
251    GetLong(Value),
252
253    #[error(r#"Expected Value::Double, Value::Float, Value::Int, Value::Long or Value::String ("NaN", "INF", "Infinity", "-INF" or "-Infinity"), got: {0:?}"#)]
254    GetDouble(Value),
255
256    #[error(r#"Expected Value::Float, Value::Double, Value::Int, Value::Long or Value::String ("NaN", "INF", "Infinity", "-INF" or "-Infinity"), got: {0:?}"#)]
257    GetFloat(Value),
258
259    #[error("Expected Value::Bytes, got: {0:?}")]
260    GetBytes(Value),
261
262    #[error("Expected Value::String, Value::Bytes or Value::Fixed, got: {0:?}")]
263    GetString(Value),
264
265    #[error("Expected Value::Enum, got: {0:?}")]
266    GetEnum(Value),
267
268    #[error("Fixed size mismatch, expected: {size}, got: {n}")]
269    CompareFixedSizes { size: usize, n: usize },
270
271    #[error("String expected for fixed, got: {0:?}")]
272    GetStringForFixed(Value),
273
274    #[error("Enum default {symbol:?} is not among allowed symbols {symbols:?}")]
275    GetEnumDefault {
276        symbol: String,
277        symbols: Vec<String>,
278    },
279
280    #[error("Enum value index {index} is out of bounds {nsymbols}")]
281    GetEnumValue { index: usize, nsymbols: usize },
282
283    #[error("Key {0} not found in decimal metadata JSON")]
284    GetDecimalMetadataFromJson(&'static str),
285
286    #[error("Could not find matching type in {schema:?} for {value:?}")]
287    FindUnionVariant { schema: UnionSchema, value: Value },
288
289    #[error("Union type should not be empty")]
290    EmptyUnion,
291
292    #[error("Array({expected:?}) expected, got {other:?}")]
293    GetArray { expected: SchemaKind, other: Value },
294
295    #[error("Map({expected:?}) expected, got {other:?}")]
296    GetMap { expected: SchemaKind, other: Value },
297
298    #[error("Record with fields {expected:?} expected, got {other:?}")]
299    GetRecord {
300        expected: Vec<(String, SchemaKind)>,
301        other: Value,
302    },
303
304    #[error("No `name` field")]
305    GetNameField,
306
307    #[error("No `name` in record field")]
308    GetNameFieldFromRecord,
309
310    #[error("Unions may not directly contain a union")]
311    GetNestedUnion,
312
313    #[error(
314        "Found two different maps while building Union: Schema::Map({0:?}), Schema::Map({1:?})"
315    )]
316    GetUnionDuplicateMap(Schema, Schema),
317
318    #[error(
319        "Found two different arrays while building Union: Schema::Array({0:?}), Schema::Array({1:?})"
320    )]
321    GetUnionDuplicateArray(Schema, Schema),
322
323    #[error("Unions cannot contain duplicate types, found at least two {0:?}")]
324    GetUnionDuplicate(SchemaKind),
325
326    #[error("Unions cannot contain more than one named schema with the same name: {0}")]
327    GetUnionDuplicateNamedSchemas(String),
328
329    #[error("One union type {0:?} must match the `default`'s value type {1:?}")]
330    GetDefaultUnion(SchemaKind, ValueKind),
331
332    #[error("`default`'s value type of field `{0}` in `{1}` must be a `{2:#}`. Got: {3:?}")]
333    GetDefaultRecordField(String, String, String, serde_json::Value),
334
335    #[error("JSON number {0} could not be converted into an Avro value as it's too large")]
336    JsonNumberTooLarge(serde_json::Number),
337
338    #[error("JSON value {0} claims to be u64 but cannot be converted")]
339    GetU64FromJson(serde_json::Number),
340
341    #[error("JSON value {0} claims to be i64 but cannot be converted")]
342    GetI64FromJson(serde_json::Number),
343
344    #[error("Cannot convert u64 to usize: {1}")]
345    ConvertU64ToUsize(#[source] std::num::TryFromIntError, u64),
346
347    #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")]
348    #[error("Cannot convert u32 to usize: {1}")]
349    ConvertU32ToUsize(#[source] std::num::TryFromIntError, u32),
350
351    #[error("Cannot convert i64 to usize: {1}")]
352    ConvertI64ToUsize(#[source] std::num::TryFromIntError, i64),
353
354    #[error("Cannot convert i32 to usize: {1}")]
355    ConvertI32ToUsize(#[source] std::num::TryFromIntError, i32),
356
357    #[error("Cannot convert i64 to u64: {1}")]
358    ConvertI64ToU64(#[source] std::num::TryFromIntError, i64),
359
360    #[error("Cannot convert i32 to u64: {1}")]
361    ConvertI32ToU64(#[source] std::num::TryFromIntError, i32),
362
363    #[error("Cannot convert i64 to u128: {1}")]
364    ConvertI64ToU128(#[source] std::num::TryFromIntError, i64),
365
366    #[error("Cannot convert i32 to u128: {1}")]
367    ConvertI32ToU128(#[source] std::num::TryFromIntError, i32),
368
369    #[error("Cannot convert usize to i64: {1}")]
370    ConvertUsizeToI64(#[source] std::num::TryFromIntError, usize),
371
372    #[error("Invalid JSON value for decimal precision/scale integer: {0}")]
373    GetPrecisionOrScaleFromJson(serde_json::Number),
374
375    #[error("Failed to parse schema from JSON")]
376    ParseSchemaJson(#[source] serde_json::Error),
377
378    #[error("Failed to read schema")]
379    ReadSchemaFromReader(#[source] std::io::Error),
380
381    #[error("Must be a JSON string, object or array")]
382    ParseSchemaFromValidJson,
383
384    #[error("Unknown primitive type: {0}")]
385    ParsePrimitive(String),
386
387    #[error("Unknown primitive type: '{0}'. Did you mean '{1}' ?")]
388    ParsePrimitiveSimilar(String, &'static str),
389
390    #[error("invalid JSON for {key:?}: {value:?}")]
391    GetDecimalMetadataValueFromJson {
392        key: String,
393        value: serde_json::Value,
394    },
395
396    #[error("The decimal precision ({precision}) must be bigger or equal to the scale ({scale})")]
397    DecimalPrecisionLessThanScale { precision: usize, scale: usize },
398
399    #[error("The decimal precision ({precision}) must be a positive number")]
400    DecimalPrecisionMuBePositive { precision: usize },
401
402    #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")]
403    #[error("Unreadable big decimal sign")]
404    BigDecimalSign,
405
406    #[error("Unreadable length for big decimal inner bytes: {0}")]
407    BigDecimalLen(#[source] Box<Error>),
408
409    #[error("Unreadable big decimal scale")]
410    BigDecimalScale,
411
412    #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")]
413    #[error("Unexpected `type` {0} variant for `logicalType`")]
414    GetLogicalTypeVariant(serde_json::Value),
415
416    #[error("No `type` field found for `logicalType`")]
417    GetLogicalTypeField,
418
419    #[error("logicalType must be a string, but is {0:?}")]
420    GetLogicalTypeFieldType(serde_json::Value),
421
422    #[error("Unknown complex type: {0}")]
423    GetComplexType(serde_json::Value),
424
425    #[error("No `type` in complex type")]
426    GetComplexTypeField,
427
428    #[error("No `type` in record field")]
429    GetRecordFieldTypeField,
430
431    #[error("No `fields` in record")]
432    GetRecordFieldsJson,
433
434    #[error("No `symbols` field in enum")]
435    GetEnumSymbolsField,
436
437    #[error("Unable to parse `symbols` in enum")]
438    GetEnumSymbols,
439
440    #[error("Invalid enum symbol name {0}")]
441    EnumSymbolName(String),
442
443    #[error("Invalid field name {0}")]
444    FieldName(String),
445
446    #[error("Duplicate field name {0}")]
447    FieldNameDuplicate(String),
448
449    #[error("Invalid schema name {0}. It must match the regex '{1}'")]
450    InvalidSchemaName(String, &'static str),
451
452    #[error("Invalid namespace {0}. It must match the regex '{1}'")]
453    InvalidNamespace(String, &'static str),
454
455    #[error(
456        "Invalid schema: There is no type called '{0}', if you meant to define a non-primitive schema, it should be defined inside `type` attribute."
457    )]
458    InvalidSchemaRecord(String),
459
460    #[error("Duplicate enum symbol {0}")]
461    EnumSymbolDuplicate(String),
462
463    #[error("Default value for an enum must be a string! Got: {0}")]
464    EnumDefaultWrongType(serde_json::Value),
465
466    #[error("Default value for an array must be an array! Got: {0}")]
467    ArrayDefaultWrongType(serde_json::Value),
468
469    #[error("Default value for an array must be an array of {0}! Found: {1:?}")]
470    ArrayDefaultWrongInnerType(Schema, Value),
471
472    #[error("Default value for a map must be an object! Got: {0}")]
473    MapDefaultWrongType(serde_json::Value),
474
475    #[error("Default value for a map must be an object with (String, {0})! Found: (String, {1:?})")]
476    MapDefaultWrongInnerType(Schema, Value),
477
478    #[error("No `items` in array")]
479    GetArrayItemsField,
480
481    #[error("No `values` in map")]
482    GetMapValuesField,
483
484    #[error("Fixed schema `size` value must be a positive integer: {0}")]
485    GetFixedSizeFieldPositive(serde_json::Value),
486
487    #[error("Fixed schema has no `size`")]
488    GetFixedSizeField,
489
490    #[deprecated(since = "0.22.0", note = "This error variant is not generated anymore")]
491    #[error("Fixed schema's default value length ({0}) does not match its size ({1})")]
492    FixedDefaultLenSizeMismatch(usize, u64),
493
494    #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")]
495    #[error("Failed to compress with flate: {0}")]
496    DeflateCompress(#[source] std::io::Error),
497
498    // no longer possible after migration from libflate to miniz_oxide
499    #[deprecated(since = "0.19.0", note = "This error can no longer occur")]
500    #[error("Failed to finish flate compressor: {0}")]
501    DeflateCompressFinish(#[source] std::io::Error),
502
503    #[error("Failed to decompress with flate: {0}")]
504    DeflateDecompress(#[source] std::io::Error),
505
506    #[cfg(feature = "snappy")]
507    #[error("Failed to compress with snappy: {0}")]
508    SnappyCompress(#[source] snap::Error),
509
510    #[cfg(feature = "snappy")]
511    #[error("Failed to get snappy decompression length: {0}")]
512    GetSnappyDecompressLen(#[source] snap::Error),
513
514    #[cfg(feature = "snappy")]
515    #[error("Snappy-compressed block is {0} bytes, too short to contain the trailing CRC32")]
516    BadSnappyLength(usize),
517
518    #[cfg(feature = "snappy")]
519    #[error("Failed to decompress with snappy: {0}")]
520    SnappyDecompress(#[source] snap::Error),
521
522    #[error("Failed to compress with zstd: {0}")]
523    ZstdCompress(#[source] std::io::Error),
524
525    #[error("Failed to decompress with zstd: {0}")]
526    ZstdDecompress(#[source] std::io::Error),
527
528    #[cfg(feature = "bzip")]
529    #[error("Failed to decompress with bzip2: {0}")]
530    Bzip2Decompress(#[source] std::io::Error),
531
532    #[cfg(feature = "xz")]
533    #[error("Failed to decompress with xz: {0}")]
534    XzDecompress(#[source] std::io::Error),
535
536    #[error("Failed to read header: {0}")]
537    ReadHeader(#[source] std::io::Error),
538
539    #[error("wrong magic in header")]
540    HeaderMagic,
541
542    #[error("Message Header mismatch. Expected: {0:?}. Actual: {1:?}")]
543    SingleObjectHeaderMismatch(Vec<u8>, Vec<u8>),
544
545    #[error("Failed to get JSON from avro.schema key in map")]
546    GetAvroSchemaFromMap,
547
548    #[error("no metadata in header")]
549    GetHeaderMetadata,
550
551    #[error("Failed to read marker bytes: {0}")]
552    ReadMarker(#[source] std::io::Error),
553
554    #[error("Failed to read block marker bytes: {0}")]
555    ReadBlockMarker(#[source] std::io::Error),
556
557    #[error("Read into buffer failed: {0}")]
558    ReadIntoBuf(#[source] std::io::Error),
559
560    #[error(
561        "Invalid sync marker! The sync marker in the data block \
562        doesn't match the file header's sync marker. This likely \
563        indicates data corruption, truncated file, or incorrectly \
564        concatenated Avro files. Verify file integrity and ensure \
565        proper file transmission or creation."
566    )]
567    GetBlockMarker,
568
569    #[error("Overflow when decoding integer value")]
570    IntegerOverflow,
571
572    #[error("Failed to read bytes for decoding variable length integer: {0}")]
573    ReadVariableIntegerBytes(#[source] std::io::Error),
574
575    #[error("Decoded integer out of range for i32: {1}: {0}")]
576    ZagI32(#[source] std::num::TryFromIntError, i64),
577
578    #[error("Did not read any bytes, block is corrupt")]
579    ReadBlock,
580
581    #[error("Failed to serialize value into Avro value: {0}")]
582    SerializeValue(String),
583
584    #[error("Failed to serialize value of type `{value_type}` using Schema::{schema:?}: {value}")]
585    SerializeValueWithSchema {
586        value_type: &'static str,
587        value: String,
588        schema: Schema,
589    },
590
591    #[error("{position} is not a valid index for fields in {schema:?}")]
592    SerializeRecordUnknownFieldIndex {
593        position: usize,
594        schema: RecordSchema,
595    },
596
597    #[error("Failed to serialize field '{field_name}' of record {record_schema:?}: {error}")]
598    SerializeRecordFieldWithSchema {
599        field_name: String,
600        record_schema: RecordSchema,
601        error: String,
602    },
603
604    #[error("Missing default for skipped field '{field_name}' of schema {schema:?}")]
605    MissingDefaultForSkippedField {
606        field_name: String,
607        schema: RecordSchema,
608    },
609
610    #[error("Failed to deserialize Avro value into value: {0}")]
611    DeserializeValue(String),
612
613    #[error("Failed to deserialize value of type {value_type} using schema {schema:?}: {value}")]
614    DeserializeSchemaAware {
615        value_type: &'static str,
616        value: String,
617        schema: Schema,
618    },
619
620    #[error("Only expected `deserialize_identifier` to be called but `{0}` was called")]
621    DeserializeIdentifier(&'static str),
622
623    #[error("Failed to write buffer bytes during flush: {0}")]
624    WriteBytes(#[source] std::io::Error),
625
626    #[error("Failed to flush inner writer during flush: {0}")]
627    FlushWriter(#[source] std::io::Error),
628
629    #[error("Failed to write marker: {0}")]
630    WriteMarker(#[source] std::io::Error),
631
632    #[error("Failed to convert JSON to string: {0}")]
633    ConvertJsonToString(#[source] serde_json::Error),
634
635    /// Error while converting float to JSON value
636    #[error("failed to convert avro float to json: {0}")]
637    ConvertF64ToJson(f64),
638
639    /// Error while resolving [`Schema::Ref`]
640    #[error("Unresolved schema reference: {0}")]
641    SchemaResolutionError(Name),
642
643    #[error("The file metadata is already flushed.")]
644    FileHeaderAlreadyWritten,
645
646    #[error("Metadata keys starting with 'avro.' are reserved for internal usage: {0}.")]
647    InvalidMetadataKey(String),
648
649    /// Error when two named schema have the same fully qualified name
650    #[error("Two named schema defined for same fullname: {0}.")]
651    AmbiguousSchemaDefinition(Name),
652
653    #[error("Signed decimal bytes length {0} not equal to fixed schema size {1}.")]
654    EncodeDecimalAsFixedError(usize, usize),
655
656    #[error("There is no entry for '{0}' in the lookup table: {1}.")]
657    NoEntryInLookupTable(String, String),
658
659    #[error("Can only encode value type {value_kind:?} as one of {supported_schema:?}")]
660    EncodeValueAsSchemaError {
661        value_kind: ValueKind,
662        supported_schema: Vec<SchemaKind>,
663    },
664    #[error("Internal buffer not drained properly. Re-initialize the single object writer struct!")]
665    IllegalSingleObjectWriterState,
666
667    #[error("Codec '{0}' is not supported/enabled")]
668    CodecNotSupported(String),
669
670    #[error("Invalid Avro data! Cannot read codec type from value that is not Value::Bytes.")]
671    BadCodecMetadata,
672
673    #[error("Cannot convert a slice to Uuid: {0}")]
674    UuidFromSlice(#[source] uuid::Error),
675
676    #[error("Expected String for Map key when serializing a flattened struct")]
677    MapFieldExpectedString,
678
679    #[error("No key for value when serializing a map")]
680    MapNoKey,
681
682    #[error(
683        "The implementation of `SchemaNameValidator` is incorrect! It returned an out-of-bounds index or provided a regex that did not capture a group named `name`"
684    )]
685    InvalidSchemaNameValidatorImplementation,
686
687    #[error(
688        "Not all tuple fields were serialized, expected to serialize element at position {position} of a {total_elements}-tuple but `SerializeTuple::end()` was called"
689    )]
690    SerializeTupleMissingElements {
691        position: usize,
692        total_elements: usize,
693    },
694}
695
696#[derive(thiserror::Error, PartialEq)]
697pub enum CompatibilityError {
698    #[error(
699        "Incompatible schema types! Writer schema is '{writer_schema_type}', but reader schema is '{reader_schema_type}'"
700    )]
701    WrongType {
702        writer_schema_type: String,
703        reader_schema_type: String,
704    },
705
706    #[error("Incompatible schema types! The {schema_type} should have been {expected_type:?}")]
707    TypeExpected {
708        schema_type: String,
709        expected_type: Vec<SchemaKind>,
710    },
711
712    #[error(
713        "Incompatible schemata! Field '{0}' in reader schema does not match the type in the writer schema"
714    )]
715    FieldTypeMismatch(String, #[source] Box<CompatibilityError>),
716
717    #[error("Incompatible schemata! Field '{0}' in reader schema must have a default value")]
718    MissingDefaultValue(String),
719
720    #[error("Incompatible schemata! Reader's symbols contain none of the writer's symbols")]
721    MissingSymbols,
722
723    #[error("Incompatible schemata! All elements in union must match for both schemas")]
724    MissingUnionElements,
725
726    #[error("Incompatible schemata! At least one element in the union must match the schema")]
727    SchemaMismatchAllUnionElements,
728
729    #[error("Incompatible schemata! Size doesn't match for fixed")]
730    FixedMismatch,
731
732    #[error(
733        "Incompatible schemata! Decimal precision and/or scale don't match, reader: ({r_precision},{r_scale}), writer: ({w_precision},{w_scale})"
734    )]
735    DecimalMismatch {
736        r_precision: usize,
737        r_scale: usize,
738        w_precision: usize,
739        w_scale: usize,
740    },
741
742    #[error(
743        "Incompatible schemata! The name must be the same for both schemas. Writer's name {writer_name} and reader's name {reader_name}"
744    )]
745    NameMismatch {
746        writer_name: String,
747        reader_name: String,
748    },
749
750    #[error(
751        "Incompatible schemata! Unknown type for '{0}'. Make sure that the type is a valid one"
752    )]
753    Inconclusive(String),
754}
755
756impl serde::ser::Error for Details {
757    fn custom<T: fmt::Display>(msg: T) -> Self {
758        Details::SerializeValue(msg.to_string())
759    }
760}
761
762impl serde::de::Error for Details {
763    fn custom<T: fmt::Display>(msg: T) -> Self {
764        Details::DeserializeValue(msg.to_string())
765    }
766}
767
768impl fmt::Debug for Details {
769    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
770        let mut msg = self.to_string();
771        if let Some(e) = self.source() {
772            msg.extend([": ", &e.to_string()]);
773        }
774        write!(f, "{msg}")
775    }
776}
777
778impl fmt::Debug for CompatibilityError {
779    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
780        let mut msg = self.to_string();
781        if let Some(e) = self.source() {
782            msg.extend([": ", &e.to_string()]);
783        }
784        write!(f, "{msg}")
785    }
786}