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