{"record":{"id":"4c2bf9693ead79d3","repo":"clockworklabs/SpacetimeDB","slug":"session-token-is-missing-in-response","errorCode":null,"errorMessage":"Session token is missing in response.","messagePattern":"Session token is missing in response\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/cli/src/subcommands/login.rs","lineNumber":199,"sourceCode":"\nimpl WebLoginSessionResponse {\n    fn approved(self) -> anyhow::Result<Option<WebLoginSessionResponseApproved>> {\n        if !self.success {\n            return Err(anyhow::anyhow!(self\n                .error\n                .clone()\n                .unwrap_or(\"Unknown error\".to_string())));\n        }\n\n        let data = self.data.ok_or(anyhow::anyhow!(\"Response data is missing.\"))?;\n        if !data.approved {\n            // Approved is false, no session token expected\n            return Ok(None);\n        }\n\n        let session_token = data\n            .session_token\n            .ok_or(anyhow::anyhow!(\"Session token is missing in response.\".to_string()))?;\n        Ok(Some(WebLoginSessionResponseApproved {\n            session_token: session_token.clone(),\n        }))\n    }\n}\n\nasync fn web_login(remote: &Url, open_browser: bool) -> Result<String, anyhow::Error> {\n    let client = reqwest::Client::new();\n\n    let response: WebLoginTokenResponse = client\n        .post(remote.join(\"/api/auth/cli/login/request-token\")?)\n        .send()\n        .await?\n        .error_for_status()?\n        .json()\n        .await?;\n\n    if !response.success {","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/cli/src/subcommands/login.rs#L181-L217","documentation":"The final step of web-login session handling: data.approved is true, meaning the user approved in the browser, but data.session_token is None. Since an approved session without a token cannot be exchanged for a SpacetimeDB token, the CLI aborts with 'Session token is missing in response.' rather than proceeding with a null credential.","triggerScenarios":"Auth API returns success:true, data:{approved:true} but omits the sessionToken field (serde rename). Server-side bug or response-mangling middlebox; in the standard flow the token is always issued on approval, so this is a contract violation by the endpoint.","commonSituations":"Auth service version skew where approval succeeds but token issuance fails silently server-side; proxies or response filters removing fields containing the word 'token'; partially failing auth backends during incidents.","solutions":["Restart `spacetime login` — if the auth backend was mid-incident, a fresh flow usually completes","Update the CLI to the latest version to match the current auth API contract","If a security product/proxy strips token fields, allowlist the SpacetimeDB auth host and retry"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for i in 1 2; do spacetime login && break; echo \"token exchange incomplete — retry $i\"; sleep 3; done","preventionTips":["Complete the approval quickly so the session token is issued while fresh","Ensure security software/proxies don't strip fields named like sessionToken from responses","Report persistent occurrences with CLI version + server host — approved-but-tokenless is a server contract violation"],"tags":["cli","login","auth","web-login","session-token","api-contract"],"backgroundTag":"auth-response-malformed","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}