clockworklabs/SpacetimeDB · error · anyhow::Error

Response data is missing.

Error message

Response data is missing.

What it means

Web-login session polling succeeded (success: true) but the response's optional `data` object is absent, so there is nothing to read approval status from. The CLI treats a success response without data as a protocol violation and errors with 'Response data is missing.' — it does not guess a default state.

Solutions

  1. Retry `spacetime login` once to rule out a one-off mangled response
  2. Update the CLI (`spacetime version`, reinstall) so its auth client matches the server's API version
  3. If behind a proxy, bypass it for the server host or verify with `curl <host>/api/auth/...` that full JSON including data comes through

Example fix

# mock endpoint — before
{ "success": true }
# after (match the protocol the CLI expects)
{ "success": true, "data": { "approved": false } }
Defensive patterns

Strategy: retry

Validate before calling

# Sanity-check the auth endpoint shape before login (self-hosted setups):
curl -sS "$HOST/api/auth/cli/login/request-token" -X POST \
  | jq -e 'has("data")' >/dev/null || echo 'auth API response missing data field — check proxy/version'

Prevention

When it happens

Trigger: The auth API returns {success: true} with no `data` key. In a healthy deployment this shape is not produced; seeing it implies a proxy/gateway rewriting the body, an API version change between CLI and server, or a malformed hand-rolled endpoint (e.g. developing against a local auth stub).

Common situations: Corporate proxies or middleboxes stripping response fields; CLI version much newer/older than the server's auth API; local development against a mock login endpoint that returns a minimal success object; CDN error pages partially overwriting JSON.

Related errors


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

Appendix: source

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

    #[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(),
        }))
    }
}

async fn web_login(remote: &Url, open_browser: bool) -> Result<String, anyhow::Error> {
    let client = reqwest::Client::new();

    let response: WebLoginTokenResponse = client

View on GitHub (pinned to 6dee26c6ef)