SeaQL/sea-orm · error

Should only have one owner

Error message

Should only have one owner

What it means

This panic comes from `Arc::into_inner(err).expect("Should only have one owner")` in the rusqlite error-mapping shim that adapts `DbErr` results for sea_schema's `Connection` trait. `Arc::into_inner` returns `None` when the inner rusqlite error is still referenced by another clone of the `Arc`, so the library treats that as an impossible invariant break and panics. It means an internal error object was shared (cloned) somewhere it was assumed to be uniquely owned while converting a connection/exec/query failure into a `RusqliteError`.

Source

Thrown at sea-orm-sync/src/database/sea_schema_rusqlite.rs:50

    }
}

fn map_result(result: Result<Vec<QueryResult>, DbErr>) -> Result<Vec<RusqliteRow>, RusqliteError> {
    match result {
        Ok(rows) => Ok(rows
            .into_iter()
            .filter_map(|r| match r.row {
                #[cfg(feature = "rusqlite")]
                QueryResultRow::Rusqlite(OurRusqliteRow { values, .. }) => {
                    Some(RusqliteRow { values })
                }
                #[allow(unreachable_patterns)]
                _ => None,
            })
            .collect()),
        Err(err) => Err(match err {
            DbErr::Conn(RuntimeErr::Rusqlite(err)) => {
                Arc::into_inner(err).expect("Should only have one owner")
            }
            DbErr::Exec(RuntimeErr::Rusqlite(err)) => {
                Arc::into_inner(err).expect("Should only have one owner")
            }
            DbErr::Query(RuntimeErr::Rusqlite(err)) => {
                Arc::into_inner(err).expect("Should only have one owner")
            }
            _ => RusqliteError::InvalidParameterName(err.to_string()),
        }),
    }
}

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Check the sea-orm / sea-schema versions for a known fix and upgrade both crates to matching latest releases.
  2. Avoid wrapping the connection in custom pooling or error-cloning layers that hold extra `Arc` references to `RuntimeErr::Rusqlite` errors.
  3. Reproduce with a minimal failing query; if refcount sharing is caused by your middleware, capture error info via `err.to_string()` before it enters the shim.
  4. Report the issue with the failing SQL and backtrace, since the `expect` documents an invariant the maintainers assume always holds.

Example fix

// before (library side, panics if Arc is shared)
DbErr::Conn(RuntimeErr::Rusqlite(err)) => {
    Arc::into_inner(err).expect("Should only have one owner")
}
// after (defensive: fall back to a synthesized error instead of panicking)
DbErr::Conn(RuntimeErr::Rusqlite(err)) => {
    Arc::try_unwrap(err).unwrap_or_else(|e| RusqliteError::InvalidParameterName(e.to_string()))
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Panics cannot be caught by Result validation; use catch_unwind around discovery calls
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
    sea_schema_discovery_query_all(&conn)
}));

Type guard

fn is_unique_arc_err(err: &DbErr) -> bool {
    match err {
        DbErr::Conn(RuntimeErr::Rusqlite(e))
        | DbErr::Exec(RuntimeErr::Rusqlite(e))
        | DbErr::Query(RuntimeErr::Rusqlite(e)) => Arc::strong_count(e) == 1,
        _ => false,
    }
}

Try / catch

let outcome = std::panic::catch_unwind(AssertUnwindSafe(|| {
    schema.query_all(select)
}));
match outcome {
    Ok(Ok(rows)) => use_rows(rows),
    Ok(Err(e)) => handle_rusqlite_error(e),
    Err(_) => log::error!("Arc ownership panic in sea_schema shim; failing over"),
}

Prevention

When it happens

Trigger: A `query_all` or `query_all_raw` call through the `sea_schema::Connection` impl for `DatabaseConnection`/`DatabaseTransaction` fails with `DbErr::Conn/RuntimeErr::Rusqlite` (or Exec/Query variants), and the wrapped `Arc<rusqlite::Error>` has refcount > 1 at the moment `map_result` unwraps it — i.e. the error was cloned before mapping.

Common situations: Hitting this usually indicates a library-level bug or an unusual error path (e.g. a SQLite error surfaced through a code path that clones the error into logs, pooled-connection wrappers, or multi-threaded sharing), rather than a user configuration mistake. It appears when using sea_schema discovery (schema introspection) over a rusqlite-backed sea-orm connection whose query fails.

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/575c9113710d671d. Report an issue: GitHub.