SeaQL/sea-orm · error

Should only have one owner

Error message

Should only have one owner

What it means

This is the sqlx counterpart of the rusqlite shim panic: in `sea_schema_shim.rs`, `map_result` calls `Arc::into_inner(err).expect("Should only have one owner")` on `DbErr::Conn(RuntimeErr::SqlxError(err))`. `Arc::into_inner` only succeeds when the error `Arc` has exactly one owner; otherwise it returns `None` and the `expect` panics. The library assumes sqlx errors are uniquely owned when converting a connection failure into a `sqlx::Error` for sea_schema.

Source

Thrown at sea-orm-sync/src/database/sea_schema_shim.rs:83

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

  1. Upgrade sea-orm/sea-schema to the latest compatible versions.
  2. Ensure no custom middleware clones `DbErr` (and thus the inner `Arc<sqlx::Error>`) before the shim maps it.
  3. Patch the shim defensively: use `Arc::try_unwrap` with an `SqlxError::AnyDriverError` fallback instead of `expect`.
  4. File an upstream issue with the connection failure and backtrace if it occurs with stock usage.

Example fix

// before
DbErr::Conn(RuntimeErr::SqlxError(err)) => {
    Arc::into_inner(err).expect("Should only have one owner")
}
// after
DbErr::Conn(RuntimeErr::SqlxError(err)) => {
    Arc::try_unwrap(err)
        .unwrap_or_else(|e| SqlxError::AnyDriverError(Box::new(DbErr::Conn(RuntimeErr::SqlxError(e)))))
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the sqlx connection is alive before schema discovery
conn.ping().map_err(|e| eprintln!("backend unreachable: {e}"))?;

Type guard

fn conn_err_unique(err: &DbErr) -> bool {
    matches!(err, DbErr::Conn(RuntimeErr::SqlxError(e))) && Arc::strong_count(e) == 1
}

Try / catch

std::panic::catch_unwind(AssertUnwindSafe(|| discovery.query_all(select)))
    .map_err(|_| anyhow!("panic in sea_schema sqlx shim"))?;

Prevention

When it happens

Trigger: `query_all`/`query_all_raw` through the sea_schema `Connection` impl fails with `DbErr::Conn(RuntimeErr::SqlxError(...))` while another clone of the `Arc<sqlx::Error>` exists at mapping time.

Common situations: Hit during schema discovery over a sqlx-backed connection (MySQL/Postgres/SQLite) when the connection itself fails (disconnect, pool closed) and some layer (logging, pooling, retry logic) retains a clone of the error. Treat it as a library invariant bug rather than a user misconfiguration.

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


AI-assisted analysis of SeaQL/sea-orm@e29bcd1b41 (2026-09-10). Data as JSON: /api/errors/edd303d4dcf28275. Report an issue: GitHub.