Skip to main content

rivven_schema/
error.rs

1//! Schema Registry errors
2
3use thiserror::Error;
4
5/// Confluent-compatible error codes
6pub mod error_codes {
7    // Subject/schema not found
8    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    // Invalid schema/compatibility
13    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    // Validation errors
19    pub const VALIDATION_ERROR: u32 = 42204;
20    pub const VERSION_DISABLED: u32 = 42205;
21    pub const REFERENCE_NOT_FOUND: u32 = 42206;
22
23    // Internal errors
24    pub const INTERNAL_ERROR: u32 = 50001;
25    pub const STORAGE_ERROR: u32 = 50002;
26}
27
28/// Schema Registry error types
29#[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    /// Get the Confluent-compatible error code
89    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    /// Get the HTTP status code
112    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
132/// Result type for schema operations
133pub 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}