{"record":{"id":"b0167feaeba72997","repo":"tonhowtf/omniget","slug":"x-login-required","errorCode":"X_LOGIN_REQUIRED","errorMessage":"X_LOGIN_REQUIRED","messagePattern":"X_LOGIN_REQUIRED","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/x/client.rs","lineNumber":169,"sourceCode":"        self.cookie.as_deref()\n    }\n\n    fn ct0(&self) -> Option<String> {\n        self.cookie.as_deref().and_then(|c| cookie_value(c, \"ct0\"))\n    }\n\n    pub fn authed(&self) -> bool {\n        self.cookie\n            .as_deref()\n            .map(|c| cookie_value(c, \"auth_token\").is_some() && cookie_value(c, \"ct0\").is_some())\n            .unwrap_or(false)\n    }\n\n    pub fn require_login(&self) -> anyhow::Result<()> {\n        if self.authed() {\n            Ok(())\n        } else {\n            Err(anyhow!(LOGIN_REQUIRED))\n        }\n    }\n\n    /// Id numerico do usuario logado (cookie `twid=u%3D<id>`).\n    pub fn user_id(&self) -> Option<String> {\n        let raw = cookie_value(self.cookie.as_deref()?, \"twid\")?;\n        let dec = urlencoding::decode(&raw)\n            .map(|c| c.to_string())\n            .unwrap_or(raw);\n        let id = dec\n            .trim()\n            .trim_start_matches(\"u=\")\n            .trim_matches('\"')\n            .to_string();\n        (!id.is_empty() && id.chars().all(|c| c.is_ascii_digit())).then_some(id)\n    }\n\n    async fn guest_token(&self, force: bool) -> anyhow::Result<String> {","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/x/client.rs#L151-L187","documentation":"The X client's require_login guard fails when the client has no authenticated session (authed() is false), returning the sentinel error with code X_LOGIN_REQUIRED. GraphQL/REST POST entry points (gql_post, rest_post_form, post_json_raw) call it before issuing requests, so any endpoint requiring a logged-in account is blocked without cookies.","triggerScenarios":"Calling any authenticated X operation (posting, following, authenticated GraphQL queries) when no login cookies/session have been established on the client.","commonSituations":"User never logged in via the app's X login flow; cookies expired or were cleared; app restarted and session was not persisted; using guest-only client for auth-required endpoints.","solutions":["Complete the X login flow in the app to establish cookies, then retry.","Re-authenticate — the stored session cookie likely expired.","Check client.authed() before calling auth-required endpoints and route to login UI.","If the operation is meant to be public, use a guest-capable call path instead of the auth-guarded one."],"exampleFix":"// before\nclient.gql_post(op, &vars).await?; // panics into X_LOGIN_REQUIRED when logged out\n// after\nif !client.authed() {\n    return Err(AppError::LoginRequired); // route user to X login flow\n}\nclient.gql_post(op, &vars).await?;","handlingStrategy":"validation","validationCode":"// before any authenticated call\nif !client.authed() {\n    navigator.go(\"/x-login\");\n    return;\n}","typeGuard":"fn ensure_authed(c: &XClient) -> anyhow::Result<()> { c.require_login() }","tryCatchPattern":"match client.gql_post(op, &vars).await {\n    Err(e) if e.to_string().contains(\"X_LOGIN_REQUIRED\") => route_to_login(),\n    other => other?,\n}","preventionTips":["Persist the X session across app restarts and refresh it when near expiry.","Gate auth-only UI actions behind an authed() check.","Show login state in the UI so users know when they are logged out.","Handle cookie clearing (browser/OS cleanup) by prompting re-login."],"tags":["x-api","authentication","session","login"],"backgroundTag":"authentication-required","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}