SeaQL/sea-orm · error

No connection

Error message

No connection

What it means

The rusqlite driver keeps the SQLite connection in a State enum (Idle, Loaned, etc.). conn() dereferences the connection and panics with "No connection" when the state is not Idle — i.e. the connection is currently loaned out (or absent), so it cannot be handed to the caller.

Source

Thrown at sea-orm-sync/src/driver/rusqlite.rs:674

        if self.transaction_depth > 0 {
            self.rollback()?;
        }
        Ok(())
    }
}

impl Drop for RusqliteInnerConnection {
    fn drop(&mut self) {
        let mut loan = self.loan.lock().unwrap();
        loan.return_(self.conn.loan());
    }
}

impl State {
    fn conn(&self) -> &RusqliteConnection {
        match self {
            State::Idle(conn) => conn,
            _ => panic!("No connection"),
        }
    }

    fn loan(&mut self) -> RusqliteConnection {
        let mut conn = State::Loaned;
        std::mem::swap(&mut conn, self);
        match conn {
            State::Idle(conn) => conn,
            _ => panic!("No connection"),
        }
    }

    fn return_(&mut self, conn: RusqliteConnection) {
        *self = State::Idle(conn);
    }
}

impl From<OwnedRow> for QueryResult {

View on GitHub (pinned to e29bcd1b41)

Solutions

  1. Avoid re-entrant/nested use of the same connection: complete or release the current loan before requesting conn() again
  2. Ensure every loan() is paired with a return of the connection on all paths (use a guard so panics/early returns restore Idle)
  3. Serialize access to the connection (Mutex/synchronization) so it is never taken while loaned

Example fix

// before
conn.query_all(q1, |row| {
    conn.query_all(q2, ...)?; // panics: connection loaned
    Ok(())
})?;
// after
let rows = conn.query_all(q1, to_model)?;
let details = conn.query_all(q2, to_detail)?; // sequential use
Defensive patterns

Strategy: fallback

Validate before calling

// never nest queries on the same connection; collect results first:
let parents = conn.query_all(parent_q, to_model)?;
for p in &parents { let kids = conn.query_all(child_q(p.id), to_model)?; }

Try / catch

let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| state.conn()));
if r.is_err() { /* the connection is loaned; retry after the outer operation completes */ }

Prevention

When it happens

Trigger: Calling conn() while the connection is in the Loaned state — typically re-entrant use of the same rusqlite connection, or use after the pool state was set to a non-Idle variant without being returned.

Common situations: Nested query execution on the same connection (a query callback triggering another query); a loaned connection never returned due to an early-return/panic path; concurrent access to a single rusqlite connection without proper synchronization.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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