zed-industries/zed · error
database not initialized
Error message
database not initialized
What it means
Database::global(cx) returns the per-App connection global set during startup, falling back to a shared LazyLock. The panic fires when no Database global was installed and the build is not test/test-support (those builds return TEST_APP_DATABASE first, which is why the code carries #[allow(unreachable_code)]). It means some code path queried the database before initialization ran — tests can pass while production panics.
Source
Thrown at crates/db/src/db.rs:88
/// inventory-registered migrations in dependency order.
#[cfg(any(test, feature = "test-support"))]
pub fn test_new() -> Self {
let name = format!("test-db-{}", uuid::Uuid::new_v4());
let connection = gpui::block_on(open_test_db::<AppMigrator>(&name));
Self(connection)
}
/// Returns the per-App connection if set, otherwise falls back to
/// the shared LazyLock.
pub fn global(cx: &App) -> &ThreadSafeConnection {
#[allow(unreachable_code)]
if let Some(db) = cx.try_global::<Self>() {
return &db.0;
} else {
#[cfg(any(feature = "test-support", test))]
return &TEST_APP_DATABASE.0;
panic!("database not initialized")
}
}
}
fn topological_sort<'a>(registrations: &[&'a DomainMigration]) -> Vec<&'a DomainMigration> {
let mut sorted: Vec<&DomainMigration> = Vec::new();
let mut visited: std::collections::HashSet<&str> = std::collections::HashSet::new();
fn visit<'a>(
name: &str,
registrations: &[&'a DomainMigration],
sorted: &mut Vec<&'a DomainMigration>,
visited: &mut std::collections::HashSet<&'a str>,
) {
if visited.contains(name) {
return;
}
if let Some(reg) = registrations.iter().find(|r| r.name == name) {View on GitHub (pinned to f4178619ac)
Solutions
- Find the init that installs the global (cx.set_global of the Database wrapper) and run it during app startup, before any entity touches the db
- Copy the full init sequence into the new entrypoint
- In test binaries, ensure the test-support feature is enabled so TEST_APP_DATABASE is used
- Grep for Database::global callers reachable before init and reorder
Example fix
// before
fn main() {
app.run(|cx| {
let conn = db::Database::global(cx); // panic: database not initialized
});
}
// after
fn main() {
app.run(|cx| {
cx.set_global(db::Database::open_default(cx)); // install the global first
let conn = db::Database::global(cx);
});
} Defensive patterns
Strategy: validation
Validate before calling
use gpui::App;
fn ensure_database(cx: &mut App) {
if cx.try_global::<db::Database>().is_none() {
cx.set_global(db::Database::open_default(cx));
}
} Type guard
fn database_ready(cx: &App) -> bool {
cx.try_global::<db::Database>().is_some()
} Prevention
- Install the Database global in every entrypoint's bootstrap, before spawning entities that query it
- Add a startup assertion that the global exists before first use
- Remember test builds silently fall back to TEST_APP_DATABASE — test green does not prove init ran
When it happens
Trigger: Calling Database::global before the startup code that does cx.set_global; a new entrypoint (CLI, embedder, plugin host) wired up without the db init sequence; init made conditional on a feature that is compiled out.
Common situations: Refactors moving init after first use; new binaries copying only part of the app bootstrap; tests green via TEST_APP_DATABASE while the shipped build crashes at first query.
Related errors
- blocking sender returned without value
- Failed to get active display list. Result: {result}
- Too many consecutive GPU errors. Last error: {error}
- WSAStartup failed: {}
- Initialize query failed to execute: {}\n\nCaused by:\n{err:#
AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20).
Data as JSON: /api/errors/9cd8f1f4f75bfc40.
Report an issue: GitHub.