clockworklabs/SpacetimeDB · error · anyhow::Error

{status}

Error message

{status}

What it means

`spacetime logs --follow` (and the log stream inside `spacetime dev`) performs an HTTP GET on the logs endpoint with num_lines=10&follow=true. When the server answers 4xx/5xx and sends no error body, the CLI bails with only the status line, e.g. `404 Not Found` or `502 Bad Gateway`. The bare status is your only clue; map it to the usual HTTP semantics.

Source

Thrown at crates/cli/src/subcommands/dev.rs:1386

    database_identity: &str,
    auth_header: &crate::util::AuthHeader,
    prefix: Option<&str>,
) -> Result<(), anyhow::Error> {
    let client = reqwest::Client::new();
    let builder = client.get(format!("{host_url}/v1/database/{database_identity}/logs"));
    let builder = add_auth_header_opt(builder, auth_header);
    let res = builder.query(&[("num_lines", "10"), ("follow", "true")]).send().await?;

    let status = res.status();
    if status.is_client_error() || status.is_server_error() {
        let mut err = res.text().await?;
        // The server doesn't always send an error description in the response
        // body (maybe it should), so default to status code + canonical reason
        // phrase (e.g. "502 Bad Gateway").
        if err.is_empty() {
            err = format!("{status}");
        }
        anyhow::bail!(err)
    }

    let term_color = if std::io::stdout().is_terminal() {
        termcolor::ColorChoice::Auto
    } else {
        termcolor::ColorChoice::Never
    };

    let mut rdr = res.bytes_stream().map_err(std::io::Error::other).into_async_read();
    let mut line = String::new();
    while rdr.read_line(&mut line).await? != 0 {
        let record = serde_json::from_str::<LogRecord<'_>>(&line)?;
        let out = termcolor::StandardStream::stdout(term_color);
        let mut out = out.lock();
        format_log_record(&mut out, &record, prefix)?;
        drop(out);
        line.clear();
    }

View on GitHub (pinned to 3653d2ed49)

Solutions

  1. List what actually exists: `spacetime list`, then retry with the exact database name
  2. Authenticate: `spacetime login` (hosted) or check `--server http://localhost:3000` points at a running local node
  3. Retry once the server is up; check `spacetime server ping` first
  4. Drop `--follow` to see whether the non-streaming log request works, isolating proxy/stream issues
  5. If behind a proxy, bypass it for the SpacetimeDB host or disable response buffering

Example fix

# before
spacetime logs mydb --follow -s https://testnet.spacetimedb.com
# after
spacetime list -s https://testnet.spacetimedb.com
spacetime logs my-real-db --follow -s https://testnet.spacetimedb.com
Defensive patterns

Strategy: validation

Validate before calling

# confirm the db exists and you are authenticated before following logs
spacetime list -s "$SERVER" | grep -q "^$DB" && spacetime logs "$DB" --follow -s "$SERVER"

Try / catch

if let Err(e) = logs_follow(&db).await {
    let msg = e.to_string();
    if msg.contains("401") || msg.contains("403") { /* re-login */ }
    else if msg.contains("404") { /* wrong db name */ }
    else if msg.contains("50") { /* server/proxy issue: retry after backoff */ }
}

Prevention

When it happens

Trigger: Following logs for a database name or identity that is not published (404); missing/expired credentials on a hosted server (401/403); the server restarting or still booting; a proxy in front of the server returning 502/504; a server version too old to support follow streaming.

Common situations: Typo in the database name or using the publish name vs the generated `spacetime init` name with a random suffix; not logged in (`spacetime login`) before hitting main.spacetimedb.com; local `spacetime start` still initializing; corporate proxies buffering or killing SSE-style streams.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@3653d2ed49 (2026-08-20). Data as JSON: /api/errors/3251bc7e644ce10a. Report an issue: GitHub.