clockworklabs/SpacetimeDB · error · anyhow::Error

Unknown error

Error message

Unknown error

What it means

During web login, the CLI polls the login-session endpoint and deserializes a WebLoginSessionResponse. If the response has success: false, the error message is taken from the response's optional `error` field; when the server omits it, the CLI falls back to the generic 'Unknown error'. So this error always represents a server-side rejection of the login session whose cause the API did not report.

Solutions

  1. Cancel and restart `spacetime login` to mint a fresh request token and session
  2. Approve the browser prompt promptly after the CLI prints the URL
  3. If it persists, check the server's status page / try `spacetime login --no-browser` and open the URL manually in a clean profile (extensions can break the approval page)

Example fix

# before: stale/expired session
(spacetime login prompt left open for a long time)
# after
spacetime login   # restart; approve promptly
Defensive patterns

Strategy: retry

Try / catch

until spacetime login; do echo 'login session rejected — retrying with a fresh token'; sleep 2; done  # bounded in practice: approve promptly

Prevention

When it happens

Trigger: The login-session API returns HTTP 200 with JSON {success: false} and no `error` field — e.g. the session token expired server-side while you sat on the browser approval page, the request token was already consumed, or an auth backend issue. Distinct from network/HTTP failures, which surface as reqwest errors before this point.

Common situations: Waiting too long (tab left open) between `spacetime login` and clicking Approve in the browser, letting the session expire; retrying a login with a stale request token behind a proxy that caches responses; maincloud auth incidents returning bare failure responses.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20). Data as JSON: /api/errors/73dd2b79d978a205. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/subcommands/login.rs:185

}

#[derive(Clone, Deserialize)]
struct WebLoginSessionData {
    approved: bool,

    #[serde(rename = "sessionToken")]
    session_token: Option<String>,
}

#[derive(Clone, Deserialize)]
struct WebLoginSessionResponseApproved {
    session_token: String,
}

impl WebLoginSessionResponse {
    fn approved(self) -> anyhow::Result<Option<WebLoginSessionResponseApproved>> {
        if !self.success {
            return Err(anyhow::anyhow!(self
                .error
                .clone()
                .unwrap_or("Unknown error".to_string())));
        }

        let data = self.data.ok_or(anyhow::anyhow!("Response data is missing."))?;
        if !data.approved {
            // Approved is false, no session token expected
            return Ok(None);
        }

        let session_token = data
            .session_token
            .ok_or(anyhow::anyhow!("Session token is missing in response.".to_string()))?;
        Ok(Some(WebLoginSessionResponseApproved {
            session_token: session_token.clone(),
        }))
    }

View on GitHub (pinned to 6dee26c6ef)