linera-io/linera-protocol · error
failed to create SQLite database file: {database_url}, error
Error message
failed to create SQLite database file: {database_url}, error: {e} What it means
When the Linera indexer opens its SQLite database and the file does not yet exist, SqliteDb::new creates it with std::fs::File::create and panics if the OS call fails. The message includes the database path and the underlying io::Error, so the real cause (usually a missing parent directory, permission denied, or a read-only filesystem) is visible at the end of the panic output.
Source
Thrown at linera-indexer/lib/src/db/sqlite/mod.rs:76
}
pub struct SqliteDatabase {
pool: SqlitePool,
}
impl SqliteDatabase {
/// Creates a new SQLite database connection.
pub async fn new(database_url: &str) -> Result<Self, SqliteError> {
if !database_url.contains("memory") {
match std::fs::exists(database_url) {
Ok(true) => {
tracing::info!(?database_url, "opening existing SQLite database");
}
Ok(false) => {
tracing::info!(?database_url, "creating new SQLite database");
// Create the database file if it doesn't exist
std::fs::File::create(database_url).unwrap_or_else(|e| {
panic!("failed to create SQLite database file: {database_url}, error: {e}")
});
}
Err(e) => {
panic!(
"failed to check SQLite database existence. file: {database_url}, error: {e}"
)
}
}
}
let pool = SqlitePoolOptions::new()
.max_connections(5)
.connect(database_url)
.await
.map_err(SqliteError::Database)?;
let db = Self { pool };
db.initialize_schema().await?;
Ok(db)
}View on GitHub (pinned to 6c226ddcb3)
Solutions
- Create the parent directory: mkdir -p /path/to/data
- Make sure the directory is writable by the running user (chown/chmod or move the DB under $HOME or /tmp)
- Check the volume is mounted read-write and has free space (df)
- Re-run and confirm the new file appears; subsequent starts take the 'opening existing SQLite database' path
Example fix
# before linera-indexer --database /var/lib/nonexistent-dir/indexer.db # after mkdir -p /var/lib/nonexistent-dir && chown "$USER" /var/lib/nonexistent-dir linera-indexer --database /var/lib/nonexistent-dir/indexer.db
Defensive patterns
Strategy: validation
Validate before calling
let path = std::path::Path::new(database_url);
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)
.unwrap_or_else(|e| panic!("cannot create {}: {e}", parent.display()));
}
assert!(
parent.map(|p| p.writable()).unwrap_or(false) || path.writable(),
"no write permission for {}",
path.display()
); Prevention
- Pre-create the data directory in deployment scripts/systemd (ExecStartPre=mkdir -p)
- Run the indexer as a user that owns the data directory
- Use absolute paths in config so relative-cwd changes can't redirect file creation
When it happens
Trigger: Launching the indexer with a --database path whose parent directory does not exist, is not writable by the current user, sits on a read-only mount, or when the disk is full. Only fires when the file is confirmed absent (Ok(false) from the existence check) and creation then fails.
Common situations: Pointing the indexer at /var/lib/... or other root-owned directories without mkdir/chown first; container deployments that mount an empty read-only volume; typos in the database path (e.g. a missing directory component); CI runs as an unprivileged user.
Related errors
- failed to check SQLite database existence. file: {database_u
- Invalid options file format: \n {options_string}
- Invalid RUST_LOG_FORMAT: `{format}`. Valid values are `json
- test-log: RUST_LOG_SPAN_EVENTS must contain filters separate
- Cannot process inbox for follow-only chain {chain_id}. Use `
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/c0dadeb2d7f31403.
Report an issue: GitHub.