1use thiserror::Error;
4
5pub mod error_codes {
7 pub const SUBJECT_NOT_FOUND: u32 = 40401;
9 pub const VERSION_NOT_FOUND: u32 = 40402;
10 pub const SCHEMA_NOT_FOUND: u32 = 40403;
11
12 pub const INVALID_SCHEMA: u32 = 42201;
14 pub const INVALID_VERSION: u32 = 42202;
15 pub const INVALID_COMPATIBILITY_LEVEL: u32 = 42203;
16 pub const INCOMPATIBLE_SCHEMA: u32 = 409;
17
18 pub const VALIDATION_ERROR: u32 = 42204;
20 pub const VERSION_DISABLED: u32 = 42205;
21 pub const REFERENCE_NOT_FOUND: u32 = 42206;
22
23 pub const INTERNAL_ERROR: u32 = 50001;
25 pub const STORAGE_ERROR: u32 = 50002;
26}
27
28#[derive(Debug, Error)]
30pub enum SchemaError {
31 #[error("Schema not found: {0}")]
32 NotFound(String),
33
34 #[error("Subject not found: {0}")]
35 SubjectNotFound(String),
36
37 #[error("Version not found: {subject} version {version}")]
38 VersionNotFound { subject: String, version: u32 },
39
40 #[error("Version disabled: {subject} version {version}")]
41 VersionDisabled { subject: String, version: u32 },
42
43 #[error("Schema reference not found: {name} references {subject} version {version}")]
44 ReferenceNotFound {
45 name: String,
46 subject: String,
47 version: u32,
48 },
49
50 #[error("Invalid schema: {0}")]
51 InvalidSchema(String),
52
53 #[error("Schema parse error: {0}")]
54 ParseError(String),
55
56 #[error("Validation error: {0}")]
57 Validation(String),
58
59 #[error("Invalid input: {0}")]
60 InvalidInput(String),
61
62 #[error("Incompatible schema: {0}")]
63 IncompatibleSchema(String),
64
65 #[error("Schema type mismatch: expected {expected}, got {actual}")]
66 TypeMismatch { expected: String, actual: String },
67
68 #[error("{0} already exists")]
69 AlreadyExists(String),
70
71 #[error("Storage error: {0}")]
72 Storage(String),
73
74 #[error("Configuration error: {0}")]
75 Config(String),
76
77 #[error("Serialization error: {0}")]
78 Serialization(String),
79
80 #[error("IO error: {0}")]
81 Io(#[from] std::io::Error),
82
83 #[error("Internal error: {0}")]
84 Internal(String),
85}
86
87impl SchemaError {
88 pub fn error_code(&self) -> u32 {
90 match self {
91 SchemaError::NotFound(_) => error_codes::SCHEMA_NOT_FOUND,
92 SchemaError::SubjectNotFound(_) => error_codes::SUBJECT_NOT_FOUND,
93 SchemaError::VersionNotFound { .. } => error_codes::VERSION_NOT_FOUND,
94 SchemaError::VersionDisabled { .. } => error_codes::VERSION_DISABLED,
95 SchemaError::ReferenceNotFound { .. } => error_codes::REFERENCE_NOT_FOUND,
96 SchemaError::InvalidSchema(_) => error_codes::INVALID_SCHEMA,
97 SchemaError::ParseError(_) => error_codes::INVALID_SCHEMA,
98 SchemaError::Validation(_) => error_codes::VALIDATION_ERROR,
99 SchemaError::InvalidInput(_) => error_codes::INVALID_SCHEMA,
100 SchemaError::IncompatibleSchema(_) => error_codes::INCOMPATIBLE_SCHEMA,
101 SchemaError::TypeMismatch { .. } => error_codes::INVALID_SCHEMA,
102 SchemaError::AlreadyExists(_) => error_codes::INVALID_SCHEMA,
103 SchemaError::Storage(_) => error_codes::STORAGE_ERROR,
104 SchemaError::Config(_) => error_codes::INTERNAL_ERROR,
105 SchemaError::Serialization(_) => error_codes::INTERNAL_ERROR,
106 SchemaError::Io(_) => error_codes::INTERNAL_ERROR,
107 SchemaError::Internal(_) => error_codes::INTERNAL_ERROR,
108 }
109 }
110
111 pub fn http_status(&self) -> u16 {
113 match self {
114 SchemaError::NotFound(_)
115 | SchemaError::SubjectNotFound(_)
116 | SchemaError::VersionNotFound { .. }
117 | SchemaError::ReferenceNotFound { .. } => 404,
118 SchemaError::VersionDisabled { .. } => 422,
119 SchemaError::InvalidSchema(_)
120 | SchemaError::ParseError(_)
121 | SchemaError::Validation(_)
122 | SchemaError::InvalidInput(_)
123 | SchemaError::TypeMismatch { .. } => 422,
124 SchemaError::IncompatibleSchema(_) => 409,
125 SchemaError::AlreadyExists(_) => 409,
126 SchemaError::Config(_) => 422,
127 _ => 500,
128 }
129 }
130}
131
132pub type SchemaResult<T> = Result<T, SchemaError>;
134
135impl From<serde_json::Error> for SchemaError {
136 fn from(e: serde_json::Error) -> Self {
137 SchemaError::Serialization(e.to_string())
138 }
139}
140
141#[cfg(feature = "avro")]
142impl From<apache_avro::Error> for SchemaError {
143 fn from(e: apache_avro::Error) -> Self {
144 SchemaError::ParseError(e.to_string())
145 }
146}