{"record":{"id":"cea0702da9fd6516","repo":"transact-rs/sqlx","slug":"downcast-to-wrong-databaseerror-type-original-err-cea070","errorCode":null,"errorMessage":"downcast to wrong DatabaseError type; original error: {e}","messagePattern":"downcast to wrong DatabaseError type; original error: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sqlx-core/src/error.rs","lineNumber":299,"sourceCode":"    /// Panics if the database error type is not `E`. This is a deliberate contrast from\n    /// `Error::downcast_ref` which returns `Option<&E>`. In normal usage, you should know the\n    /// specific error type. In other cases, use `try_downcast_ref`.\n    pub fn downcast_ref<E: DatabaseError>(&self) -> &E {\n        self.try_downcast_ref().unwrap_or_else(|| {\n            panic!(\"downcast to wrong DatabaseError type; original error: {self}\")\n        })\n    }\n\n    /// Downcast this generic database error to a specific database error type.\n    ///\n    /// # Panics\n    ///\n    /// Panics if the database error type is not `E`. This is a deliberate contrast from\n    /// `Error::downcast` which returns `Option<E>`. In normal usage, you should know the\n    /// specific error type. In other cases, use `try_downcast`.\n    pub fn downcast<E: DatabaseError>(self: Box<Self>) -> Box<E> {\n        self.try_downcast()\n            .unwrap_or_else(|e| panic!(\"downcast to wrong DatabaseError type; original error: {e}\"))\n    }\n\n    /// Downcast a reference to this generic database error to a specific\n    /// database error type.\n    #[inline]\n    pub fn try_downcast_ref<E: DatabaseError>(&self) -> Option<&E> {\n        self.as_error().downcast_ref()\n    }\n\n    /// Downcast this generic database error to a specific database error type.\n    #[inline]\n    pub fn try_downcast<E: DatabaseError>(self: Box<Self>) -> Result<Box<E>, Box<Self>> {\n        if self.as_error().is::<E>() {\n            Ok(self.into_error().downcast().unwrap())\n        } else {\n            Err(self)\n        }\n    }","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/transact-rs/sqlx/blob/03af8bcc5711a1935580a54bea249c219a0c217d/sqlx-core/src/error.rs#L281-L317","documentation":"DatabaseError::downcast() (boxed variant, sqlx-core/src/error.rs:299) panics when `Box<dyn DatabaseError>` cannot be converted into the requested concrete error type E. It is the owning counterpart of downcast_ref; a failed downcast means the error came from a different database backend than assumed. The panic message includes the original error for diagnosis.","triggerScenarios":"`err.downcast::<MySqlDatabaseError>()` on a boxed error originating from Postgres/SQLite, typically inside a shared helper that takes `Box<dyn DatabaseError>` or stores errors from mixed pools, then unwraps to one specific backend type.","commonSituations":"Middleware or retry layers that persist and later re-downcast database errors assuming a fixed backend; test suites where a different database feature is enabled than in production code paths; migrating an app from one database to another without updating downcast targets.","solutions":["Switch to `try_downcast::<E>()` which returns Option/Result and handle the mismatch gracefully.","Track the backend alongside stored errors (enum wrapper) so the correct concrete type is requested.","Restructure to keep backend-specific error handling adjacent to the backend-specific pool that produced the error."],"exampleFix":"// before\nlet mysql_err = boxed_err.downcast::<MySqlDatabaseError>();\n\n// after\nmatch boxed_err.try_downcast::<MySqlDatabaseError>() {\n    Some(e) => handle_mysql(e),\n    None => log::warn!(\"non-MySQL db error: {boxed_err}\"),\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"fn try_owned_downcast(db_err: Box<dyn sqlx::error::DatabaseError>) -> Option<Box<sqlx::mysql::MySqlDatabaseError>> {\n    db_err.try_downcast::<sqlx::mysql::MySqlDatabaseError>()\n}","tryCatchPattern":"// Use the fallible variant:\nlet Ok(mysql_err) = boxed_err.try_downcast::<MySqlDatabaseError>() else {\n    return handle_other(boxed_err);\n};","preventionTips":["Never store bare Box<dyn DatabaseError> when the concrete type will be needed later — store an enum with the backend tag","Default to try_downcast in shared/retry/middleware layers","Add tests covering error paths for every database backend you support"],"tags":["panic","downcast","database-error","sqlx"],"backgroundTag":"wrong-error-downcast","analyzedSha":"03af8bcc5711a1935580a54bea249c219a0c217d","analyzedAt":"2026-09-03T15:01:28.752Z","contentChangedAt":"2026-09-03T15:01:28.752Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}