tursodatabase/turso · error

Error: cannot open "{}" – {}

Error message

Error: cannot open "{}" – {}

What it means

Thrown by read_sql_file, the .read dot-command, when File::open on the given path fails; the OS error (No such file or directory, Permission denied, Is a directory) is appended to the message (cli/app.rs:2068). It fires before any line is read, so no script statements have executed.

Source

Thrown at cli/app.rs:2084

    fn clone_database(&mut self, output_file: &str) -> anyhow::Result<()> {
        use std::path::Path;
        if Path::new(output_file).exists() {
            anyhow::bail!("Refusing to overwrite existing file: {output_file}");
        }
        let io: Arc<dyn turso_core::IO> = Arc::new(turso_core::PlatformIO::new()?);
        let db = Database::open_file(io.clone(), output_file, Arc::new(SqliteDialect))?;
        let target = db.connect()?;

        let mut applier = ApplyWriter::new(&target);
        Self::dump_database_from_conn(false, self.conn.clone(), &mut applier, StderrProgress)?;
        applier.finish()?;
        Ok(())
    }

    fn read_sql_file(&mut self, path: &str) -> anyhow::Result<()> {
        let file =
            File::open(path).map_err(|e| anyhow!("Error: cannot open \"{}\" – {}", path, e))?;
        let reader = BufReader::new(file);

        let mut query_buffer = String::new();
        let mut state = ReadState::default();

        for line in reader.lines() {
            let line = line
                .map_err(|e| anyhow!("Error: file \"{}\" is not valid UTF-8 text – {}", path, e))?;

            if !query_buffer.is_empty() {
                query_buffer.push('\n');
            }
            query_buffer.push_str(&line);

            state.process(&line);

            if state.is_complete() {
                self.run_query(&query_buffer);

View on GitHub (pinned to 492c4a71cd)

Solutions

  1. Check the exact path shown in the message exists (ls it)
  2. Use an absolute path, or a path relative to the shell's current working directory
  3. Fix permissions (chmod/chown) if the OS error is Permission denied
  4. Quote paths that contain spaces

Example fix

-- before
.read scripts/init.sql   -- ERROR: cannot open "scripts/init.sql"
-- after
.read /work/repo/scripts/init.sql
Defensive patterns

Strategy: validation

Validate before calling

let p = std::path::Path::new(path);
anyhow::ensure!(p.is_file(), "{} is not a readable file", p.display());

Prevention

When it happens

Trigger: `.read missing.sql`; a relative path resolved against a different working directory; a file without read permission; a path that points at a directory.

Common situations: Relative paths resolved from where tursodb was launched rather than where the script lives; typos; permission-restricted mounts in containers; unquoted paths containing spaces.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of tursodatabase/turso@492c4a71cd (2026-08-20). Data as JSON: /api/errors/49ddbfc3e3fb520d. Report an issue: GitHub.