@@ -112,6 +112,30 @@ fn classify_error(e: &dkdc_db_core::Error) -> StatusCode {
112112 }
113113}
114114
115+ /// Return a user-safe error message, hiding internal details for server errors.
116+ ///
117+ /// User-facing errors (Validation, Schema, WriteOnReadPath, ReadOnWritePath) are
118+ /// returned as-is since they contain information the caller needs to fix their request.
119+ /// Internal errors (Turso, DataFusion, Arrow, Io, Config) are replaced with a generic
120+ /// message — the full error is already logged server-side via tracing::warn.
121+ fn sanitize_error ( e : & dkdc_db_core:: Error ) -> String {
122+ match e {
123+ dkdc_db_core:: Error :: Validation ( msg) => format ! ( "validation error: {msg}" ) ,
124+ dkdc_db_core:: Error :: WriteOnReadPath ( msg) => {
125+ format ! ( "write attempted through read path: {msg}" )
126+ }
127+ dkdc_db_core:: Error :: ReadOnWritePath ( msg) => {
128+ format ! ( "read attempted through write path: {msg}" )
129+ }
130+ dkdc_db_core:: Error :: Schema ( msg) => format ! ( "schema error: {msg}" ) ,
131+ dkdc_db_core:: Error :: Turso ( _)
132+ | dkdc_db_core:: Error :: DataFusion ( _)
133+ | dkdc_db_core:: Error :: Arrow ( _)
134+ | dkdc_db_core:: Error :: Io ( _)
135+ | dkdc_db_core:: Error :: Config ( _) => "internal server error" . to_string ( ) ,
136+ }
137+ }
138+
115139pub fn batches_to_response ( batches : & [ dkdc_db_core:: RecordBatch ] ) -> QueryResponse {
116140 let mut columns = Vec :: new ( ) ;
117141 let mut rows = Vec :: new ( ) ;
@@ -183,7 +207,7 @@ async fn create_db(
183207 }
184208 Err ( e) => {
185209 tracing:: warn!( db = %req. name, error = %e, "create_db failed" ) ;
186- error_response ( classify_error ( & e) , e ) . into_response ( )
210+ error_response ( classify_error ( & e) , sanitize_error ( & e ) ) . into_response ( )
187211 }
188212 }
189213}
@@ -196,7 +220,7 @@ async fn drop_db(State(mgr): State<AppState>, Path(name): Path<String>) -> impl
196220 }
197221 Err ( e) => {
198222 tracing:: warn!( db = %name, error = %e, "drop_db failed" ) ;
199- error_response ( classify_error ( & e) , e ) . into_response ( )
223+ error_response ( classify_error ( & e) , sanitize_error ( & e ) ) . into_response ( )
200224 }
201225 }
202226}
@@ -218,7 +242,7 @@ async fn execute(
218242 }
219243 Err ( e) => {
220244 tracing:: warn!( db = %name, error = %e, "execute failed" ) ;
221- error_response ( classify_error ( & e) , e ) . into_response ( )
245+ error_response ( classify_error ( & e) , sanitize_error ( & e ) ) . into_response ( )
222246 }
223247 }
224248}
@@ -228,7 +252,7 @@ async fn query(State(mgr): State<AppState>, Json(req): Json<SqlRequest>) -> impl
228252 Ok ( batches) => ( StatusCode :: OK , Json ( batches_to_response ( & batches) ) ) . into_response ( ) ,
229253 Err ( e) => {
230254 tracing:: warn!( error = %e, "query failed" ) ;
231- error_response ( classify_error ( & e) , e ) . into_response ( )
255+ error_response ( classify_error ( & e) , sanitize_error ( & e ) ) . into_response ( )
232256 }
233257 }
234258}
@@ -242,7 +266,7 @@ async fn query_oltp(
242266 Ok ( batches) => ( StatusCode :: OK , Json ( batches_to_response ( & batches) ) ) . into_response ( ) ,
243267 Err ( e) => {
244268 tracing:: warn!( db = %name, error = %e, "query_oltp failed" ) ;
245- error_response ( classify_error ( & e) , e ) . into_response ( )
269+ error_response ( classify_error ( & e) , sanitize_error ( & e ) ) . into_response ( )
246270 }
247271 }
248272}
@@ -252,7 +276,7 @@ async fn list_tables(State(mgr): State<AppState>, Path(name): Path<String>) -> i
252276 Ok ( tables) => ( StatusCode :: OK , Json ( tables) ) . into_response ( ) ,
253277 Err ( e) => {
254278 tracing:: warn!( db = %name, error = %e, "list_tables failed" ) ;
255- error_response ( classify_error ( & e) , e ) . into_response ( )
279+ error_response ( classify_error ( & e) , sanitize_error ( & e ) ) . into_response ( )
256280 }
257281 }
258282}
@@ -265,7 +289,7 @@ async fn table_schema(
265289 Ok ( batches) => ( StatusCode :: OK , Json ( batches_to_response ( & batches) ) ) . into_response ( ) ,
266290 Err ( e) => {
267291 tracing:: warn!( db = %name, table = %table, error = %e, "table_schema failed" ) ;
268- error_response ( classify_error ( & e) , e ) . into_response ( )
292+ error_response ( classify_error ( & e) , sanitize_error ( & e ) ) . into_response ( )
269293 }
270294 }
271295}
0 commit comments