{"record":{"id":"4b6040da691fb204","repo":"clockworklabs/SpacetimeDB","slug":"response-data-is-missing","errorCode":null,"errorMessage":"Response data is missing.","messagePattern":"Response data is missing\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/cli/src/subcommands/login.rs","lineNumber":191,"sourceCode":"    #[serde(rename = \"sessionToken\")]\n    session_token: Option<String>,\n}\n\n#[derive(Clone, Deserialize)]\nstruct WebLoginSessionResponseApproved {\n    session_token: String,\n}\n\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","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/cli/src/subcommands/login.rs#L173-L209","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Retry `spacetime login` once to rule out a one-off mangled response","Update the CLI (`spacetime version`, reinstall) so its auth client matches the server's API version","If behind a proxy, bypass it for the server host or verify with `curl <host>/api/auth/...` that full JSON including data comes through"],"exampleFix":"# mock endpoint — before\n{ \"success\": true }\n# after (match the protocol the CLI expects)\n{ \"success\": true, \"data\": { \"approved\": false } }","handlingStrategy":"retry","validationCode":"# Sanity-check the auth endpoint shape before login (self-hosted setups):\ncurl -sS \"$HOST/api/auth/cli/login/request-token\" -X POST \\\n  | jq -e 'has(\"data\")' >/dev/null || echo 'auth API response missing data field — check proxy/version'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep CLI and server versions aligned; response shapes evolve together","Bypass proxies/middleboxes for the auth host if fields go missing","When mocking auth endpoints in tests, include the full data object the real API returns"],"tags":["cli","login","auth","web-login","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"}