linera-io/linera-protocol · error

failed to check SQLite database existence. file: {database_u

Error message

failed to check SQLite database existence. file: {database_url}, error: {e}

What it means

Before creating or opening its SQLite file, the indexer probes whether the path exists; if that probe itself returns an error (as opposed to a clean yes/no), the constructor panics. This means the filesystem could not answer 'does this file exist' — typically because a path component is unreadable, a component is a plain file rather than a directory, or the path traverses a directory without search (execute) permission.

Source

Thrown at linera-indexer/lib/src/db/sqlite/mod.rs:80

}

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)
    }

    /// Initialize the database schema
    async fn initialize_schema(&self) -> Result<(), SqliteError> {
        // Create core tables

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Verify each component of the path is a directory and traversable: namei -l /path/to/indexer.db shows the first failing component
  2. Fix permissions on the failing component (chmod o+x or chown) or choose a path you fully own
  3. Remove stale file-where-a-directory-is-expected components
  4. If on a network mount, ensure it is mounted and healthy before starting the indexer

Example fix

# before (parent dir not traversable by the service user)
sudo -u indexer linera-indexer --database /home/deploy/indexer.db

# after
sudo mkdir -p /var/lib/linera-indexer && sudo chown indexer /var/lib/linera-indexer
sudo -u indexer linera-indexer --database /var/lib/linera-indexer/indexer.db
Defensive patterns

Strategy: validation

Validate before calling

let path = std::path::Path::new(database_url);
for ancestor in path.ancestors().skip(1) {
    match std::fs::metadata(ancestor) {
        Ok(md) if md.is_dir() => {}
        Ok(_) => panic!("{ancestor} is a file, not a directory"),
        Err(e) => panic!("cannot stat {ancestor}: {e}"),
    }
}

Prevention

When it happens

Trigger: Database path like /root/data/indexer.db when /root is mode 700 and the process runs as another user; a path component that is a regular file (e.g. data.txt/indexer.db); path on a failing/unmounted NFS or FUSE mount. Distinguished from error 21: here the stat/existence check fails, not the create.

Common situations: Running under a container service account with restricted home directories; stale absolute paths baked into config files after a directory layout change; security-hardened systems with restrictive parent-directory modes.

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/e733991e67001463. Report an issue: GitHub.