SeaQL/sea-orm · warning
Should only have one owner
Error message
Should only have one owner
What it means
In the sea_schema shim's `map_result`, when a query fails with a `DbErr` wrapping a `sqlx` error inside an `Arc`, the code calls `Arc::into_inner(err).expect("Should only have one owner")` to unwrap the sqlx error. `Arc::into_inner` returns `None` if other clones of the Arc exist — the panic asserts the error is uniquely owned at that point.
Source
Thrown at src/database/sea_schema_shim.rs:92
fn map_result(result: Result<Vec<QueryResult>, DbErr>) -> Result<Vec<SqlxRow>, SqlxError> {
match result {
Ok(rows) => Ok(rows
.into_iter()
.filter_map(|r| match r.row {
#[cfg(feature = "sqlx-mysql")]
QueryResultRow::SqlxMySql(r) => Some(SqlxRow::MySql(r)),
#[cfg(feature = "sqlx-postgres")]
QueryResultRow::SqlxPostgres(r) => Some(SqlxRow::Postgres(r)),
#[cfg(feature = "sqlx-sqlite")]
QueryResultRow::SqlxSqlite(r) => Some(SqlxRow::Sqlite(r)),
#[allow(unreachable_patterns)]
_ => None,
})
.collect()),
Err(err) => Err(match err {
DbErr::Conn(RuntimeErr::SqlxError(err)) => {
Arc::into_inner(err).expect("Should only have one owner")
}
DbErr::Exec(RuntimeErr::SqlxError(err)) => {
Arc::into_inner(err).expect("Should only have one owner")
}
DbErr::Query(RuntimeErr::SqlxError(err)) => {
Arc::into_inner(err).expect("Should only have one owner")
}
_ => SqlxError::AnyDriverError(Box::new(err)),
}),
}
}
View on GitHub (pinned to e29bcd1b41)
Solutions
- Drop/clone-free other references: ensure the DbErr is moved (not cloned) into the shim mapping path.
- Avoid keeping clones of the error while calling sea_schema query helpers; clone the string representation instead.
- If it recurs, restructure so each error is consumed once, e.g. map to your own error type at the boundary before passing along.
Example fix
// before
let err_clone = err.clone();
log::error!("{}", err_clone);
schema_discovery::map_result(err); // Arc still shared -> panic
// after
log::error!("{}", err); // log first
schema_discovery::map_result(err); // move uniquely-owned error Defensive patterns
Strategy: try-catch
Try / catch
// the panic comes from Arc::into_inner inside the library; guard by not cloning the error:
let outcome = discovery.query_all(...).await;
match outcome {
Ok(rows) => { /* ... */ }
Err(e) => {
// consume e exactly once; log via formatted string, never clone the DbErr
return Err(MyError::from(e));
}
} Prevention
- Move DbErr values instead of cloning them when handing them to schema helpers.
- Convert library errors into your own error type at the API boundary.
- Avoid sharing one DbErr across threads/tasks.
When it happens
Trigger: The same `DbErr::Conn/Exec/Query(RuntimeErr::SqlxError(...))` value was cloned before being returned from `query_all`/`query_all_raw`, so the Arc has refcount > 1 when mapped. Multi-threaded code sharing the error also triggers it.
Common situations: Application code storing or cloning the returned DbErr (e.g. logging wrappers, error aggregation) while also passing it into schema-inspection helpers; concurrent tasks sharing one error value.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Should only have one owner
- Not MySQL Connection
- Not Postgres Connection
- Not SQLite Connection
- Not MySQL Connection
AI-assisted analysis of SeaQL/sea-orm@e29bcd1b41 (2026-09-10).
Data as JSON: /api/errors/aa30fba25e51f3ae.
Report an issue: GitHub.