tursodatabase/turso · error · anyhow::Error

local sync server failed to start after {SPAWN_ATTEMPTS} att

Error message

local sync server failed to start after {SPAWN_ATTEMPTS} attempts

What it means

Returned when TursoServer::spawn exhausts SPAWN_ATTEMPTS (10) attempts without the sync server becoming ready. Each attempt that exits early (typically because the port was reserved or taken) is retried on another port; this error means every attempt either exited or timed out (bindings/rust/src/sync.rs:1174). The per-attempt stderr above the error says which.

Source

Thrown at bindings/rust/src/sync.rs:1271

                                     before becoming ready (attempt {attempt}/{SPAWN_ATTEMPTS})"
                                );
                                break;
                            }
                            None => {
                                if started.elapsed() > READY_TIMEOUT {
                                    let _ = child.kill();
                                    let _ = child.wait();
                                    return Err(anyhow!(
                                        "local sync server on port {port} did not become ready \
                                         within {READY_TIMEOUT:?}"
                                    ));
                                }
                            }
                        }
                        sleep(Duration::from_millis(100));
                    }
                }
                Err(anyhow!(
                    "local sync server failed to start after {SPAWN_ATTEMPTS} attempts"
                ))
            }
        }

        pub fn db_url(&self) -> &str {
            &self.db_url
        }

        pub async fn db_sql(&self, sql: &str) -> Result<Vec<Vec<Value>>> {
            let resp = self
                .client
                .post(format!("{}{}/v2/pipeline", self.user_url, self.db_prefix))
                .header("Host", &self.host)
                .json(&json!({
                    "requests": [{
                        "type": "execute",
                        "stmt": { "sql": sql }

View on GitHub (pinned to 492c4a71cd)

Solutions

  1. Kill leftover servers (pkill -f tursodb, or tman kill) and rerun the test
  2. Verify the binary the harness spawns: run tursodb sync serve --help manually and confirm it exists
  3. Check the 'exited with {status}' lines the harness prints per attempt - they carry the real exit cause
  4. Free ports or widen the ephemeral port range available to the test user

Example fix

# before: tests fail with 'local sync server failed to start after 10 attempts'
pgkill() { pkill -f 'tursodb.*sync'; }
pgkill && sleep 1 && cargo test -p turso sync_tests
Defensive patterns

Strategy: retry

Validate before calling

let out = std::process::Command::new("tursodb")
    .args(["sync", "serve", "--help"])
    .output()?;
anyhow::ensure!(out.status.success(), "tursodb binary lacks sync serve");

Try / catch

match TursoServer::spawn(&ctx).await {
    Ok(server) => Ok(server),
    Err(e) if e.to_string().contains("SPAWN_ATTEMPTS").or(e.to_string().contains("failed to start")) => {
        let _ = std::process::Command::new("pkill").arg("-f").arg("tursodb").status();
        TursoServer::spawn(&ctx).await
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: The spawned binary cannot start at all - wrong binary on PATH, tursodb built without the sync serve subcommand, or all candidate ports occupied; also reached when each attempt burns the full 60s readiness timeout on a starved machine.

Common situations: Leftover tursodb server processes from a killed test run holding ports; PATH resolving to an old binary after a rebase; CI environments with a narrow usable port range; a previous failed run leaving orphans behind.

Related errors


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