{"record":{"id":"46e4ef868e0cdc31","repo":"Kuberwastaken/claurst","slug":"invalid-jwt-expected-at-least-2-dot-separated-seg","errorCode":null,"errorMessage":"Invalid JWT: expected at least 2 dot-separated segments","messagePattern":"Invalid JWT: expected at least 2 dot-separated segments","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-rust/crates/bridge/src/lib.rs","lineNumber":63,"sourceCode":"    /// Trusted-device identifier embedded by the server.\r\n    pub device_id: Option<String>,\r\n    /// Session identifier embedded by the server.\r\n    pub session_id: Option<String>,\r\n}\r\n\r\nimpl JwtClaims {\r\n    /// Decode a JWT payload segment without verifying the signature.\r\n    ///\r\n    /// Strips the `sk-ant-si-` session-ingress prefix if present, then\r\n    /// base64url-decodes the second `.`-separated segment and JSON-parses it.\r\n    /// Returns an error if the token is malformed or the JSON is invalid.\r\n    pub fn decode(token: &str) -> anyhow::Result<Self> {\r\n        // Strip session-ingress prefix used by Anthropic's ingress tokens.\r\n        let jwt = token.strip_prefix(\"sk-ant-si-\").unwrap_or(token);\r\n\r\n        let parts: Vec<&str> = jwt.split('.').collect();\r\n        if parts.len() < 2 {\r\n            anyhow::bail!(\"Invalid JWT: expected at least 2 dot-separated segments\");\r\n        }\r\n\r\n        let raw = URL_SAFE_NO_PAD\r\n            .decode(parts[1])\r\n            .context(\"JWT payload is not valid base64url\")?;\r\n\r\n        serde_json::from_slice::<Self>(&raw)\r\n            .context(\"JWT payload is not valid JSON matching JwtClaims\")\r\n    }\r\n\r\n    /// Returns `true` if the `exp` claim is in the past.\r\n    ///\r\n    /// When `exp` is absent the token is treated as non-expired (permissive\r\n    /// default), matching the TypeScript behaviour in `jwtUtils.ts`.\r\n    pub fn is_expired(&self) -> bool {\r\n        if let Some(exp) = self.exp {\r\n            let now = chrono::Utc::now().timestamp();\r\n            exp < now\r","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/Kuberwastaken/claurst/blob/b0637c97ec34144387cbf2f74f65df6d16a6cef1/src-rust/crates/bridge/src/lib.rs#L45-L81","documentation":"`wait_for_authorization_code` parses the callback URL the browser redirected to and searches its query pairs for a `code` parameter. If the OAuth provider redirected back without an authorization code, this error is returned. It means the provider responded to the authorization request with something other than a successful code grant (typically an error redirect).","triggerScenarios":"The provider redirects to `callback_path` with query params that contain no `code` key — e.g. `?error=access_denied`, `?error=invalid_scope`, or an empty/malformed callback URL.","commonSituations":"User denies the consent prompt; the OAuth client's redirect URI, client ID, or scopes are misconfigured so the provider rejects the request; the auth_url was built with a mismatched state/scope; the provider appends the code under a different parameter name than `code`.","solutions":["Inspect the actual callback URL (browser address bar or server logs) for an `error` query parameter and fix the OAuth client config it points to.","Verify `session.auth_url` was built with the exact redirect URI registered with the provider.","Re-run the auth flow and accept the consent prompt when asked.","Confirm the provider uses the standard `code` query parameter for the authorization-code flow."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"fn callback_has_code(url: &str) -> bool {\n    url::Url::parse(url)\n        .map(|u| u.query_pairs().any(|(k, _)| k == \"code\"))\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check the provider's error query param (error=access_denied, etc.) in logs before retrying","Validate redirect_uri, client_id, and scopes against the provider's registered OAuth client before starting the flow","Instruct users to accept the consent prompt"],"tags":["oauth","authorization-code","query-params"],"backgroundTag":"missing-required-argument","analyzedSha":"b0637c97ec34144387cbf2f74f65df6d16a6cef1","analyzedAt":"2026-09-10T00:24:58.650Z","contentChangedAt":"2026-09-10T00:24:58.650Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}