{"record":{"id":"ad852b7af8aade1c","repo":"twentyhq/twenty","slug":"no-getauthtokensfromssoexchangetoken-result","errorCode":null,"errorMessage":"No getAuthTokensFromSSOExchangeToken result","messagePattern":"No getAuthTokensFromSSOExchangeToken result","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/twenty-front/src/modules/auth/hooks/useRedeemSSOExchangeToken.ts","lineNumber":34,"sourceCode":"  );\n  const [getAuthTokensFromSSOExchangeToken] = useMutation(\n    GetAuthTokensFromSsoExchangeTokenDocument,\n  );\n\n  const redeemSSOExchangeToken = useCallback(\n    async (ssoExchangeToken: string) => {\n      // Keeps PageChangeEffect from consuming returnToPath mid token swap, and\n      // drops any stale pair so the resume waits for the one being redeemed\n      setIsAppEffectRedirectEnabled(false);\n      setTokenPair(null);\n\n      try {\n        const { data } = await getAuthTokensFromSSOExchangeToken({\n          variables: { ssoExchangeToken },\n        });\n\n        if (!isDefined(data?.getAuthTokensFromSSOExchangeToken)) {\n          throw new Error('No getAuthTokensFromSSOExchangeToken result');\n        }\n\n        setTokenPair(data.getAuthTokensFromSSOExchangeToken.tokens);\n      } catch (error: unknown) {\n        enqueueErrorSnackBar(\n          CombinedGraphQLErrors.is(error)\n            ? { apolloError: error }\n            : { message: error instanceof Error ? error.message : undefined },\n        );\n      } finally {\n        setIsAppEffectRedirectEnabled(true);\n      }\n    },\n    [\n      getAuthTokensFromSSOExchangeToken,\n      setTokenPair,\n      setIsAppEffectRedirectEnabled,\n      enqueueErrorSnackBar,","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/twentyhq/twenty/blob/1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6/packages/twenty-front/src/modules/auth/hooks/useRedeemSSOExchangeToken.ts#L16-L52","documentation":"Thrown by useRedeemSSOExchangeToken (useRedeemSSOExchangeToken.ts:31-36) when the getAuthTokensFromSSOExchangeToken GraphQL mutation returns no data on the getAuthTokensFromSSOExchangeToken field. This typically means the ssoExchangeToken was invalid, expired, or already consumed. The thrown error is caught in the same hook and surfaced as an error snack bar.","triggerScenarios":"SSO login flow where the exchange token (passed via the redirect URL) is rejected by the server: data.getAuthTokensFromSSOExchangeToken is null/undefined, so the inner check fails.","commonSituations":"User revisits an old SSO redirect link whose token was already consumed; clock skew causing premature token expiry; IdP configuration mismatch; network/apollo error masking the field to null; the exchange token was tampered with.","solutions":["Re-initiate the SSO login flow from the IdP to obtain a fresh exchange token.","Verify the exchange token arrives unmodified in the redirect URL query string.","Check server logs for getAuthTokensFromSSOExchangeToken rejection reasons (token expired vs. invalid).","Ensure clocks are synced between client and server to avoid premature expiry."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// The hook already wraps this in try/catch and surfaces a snack bar.\n// To add custom recovery:\ntry {\n  await redeemSSOExchangeToken(token);\n} catch (err) {\n  if (err.message === 'No getAuthTokensFromSSOExchangeToken result') {\n    // redirect the user back to the SSO login entry point\n  }\n}","preventionTips":["Do not bookmark or reuse SSO redirect URLs.","Sync client/server clocks to avoid premature token expiry.","Handle the exchange immediately on redirect arrival.","Surface a clear re-login CTA when redemption fails."],"tags":["frontend","auth","sso","graphql","apollo"],"backgroundTag":null,"analyzedSha":"1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6","analyzedAt":"2026-08-12T15:37:27.593Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}