RocketChat/Rocket.Chat · error · Error
Invalid response from login code redemption
Error message
Invalid response from login code redemption
What it means
Thrown by the useOAuthLogin mutation when POST /v1/loginCode.redeem returns a response missing loginToken or userId. The redemption call succeeded at the HTTP level but the payload is incomplete, so no token is available to complete the deep-link or loginWithToken flow.
Source
Thrown at apps/meteor/client/views/root/hooks/useOAuthLogin.ts:19
import { useEndpoint, useRouter, useSearchParameter, useLoginWithToken } from '@rocket.chat/ui-contexts';
import { useMutation } from '@tanstack/react-query';
import { useEffect } from 'react';
import { buildDeepLinkURL } from '../../../lib/buildAuthDeeplinkURL';
export const useOAuthLogin = () => {
const router = useRouter();
const loginCode = useSearchParameter('loginCode');
const loginClient = useSearchParameter('loginClient');
const redeemLoginCode = useEndpoint('POST', '/v1/loginCode.redeem');
const loginWithToken = useLoginWithToken();
const { mutate: redeemLoginCodeMutation } = useMutation({
mutationFn: async (loginCode: string) => {
const { loginToken, userId } = await redeemLoginCode({ code: loginCode });
if (!loginToken || !userId) {
throw new Error('Invalid response from login code redemption');
}
return { loginToken, userId };
},
onSuccess: async ({ loginToken, userId }) => {
if (loginClient === 'desktop' || loginClient === 'mobile') {
window.location.href = buildDeepLinkURL(loginToken, userId);
return;
}
await loginWithToken(loginToken);
router.navigate('/home', { replace: true });
},
onError: (error) => {
console.error('Failed to redeem login code for client redirect', error);
router.navigate('/login', { replace: true });
},
});View on GitHub (pinned to f9d3ec372b)
Solutions
- Regenerate the login code (restart the OAuth/login flow) so a fresh, unconsumed code is redeemed.
- Verify the loginCode.redeem endpoint on the server returns both loginToken and userId for valid codes.
- In onError, redirect the user back to the login page with a clear 'code expired' message.
Example fix
// before
const { loginToken, userId } = await redeemLoginCode({ code: loginCode });
if (!loginToken || !userId) {
throw new Error('Invalid response from login code redemption');
}
// after
const res = await redeemLoginCode({ code: loginCode });
if (!res?.loginToken || !res?.userId) {
throw new Error(`Invalid response from login code redemption (token=${!!res?.loginToken}, userId=${!!res?.userId})`);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Sanity-check the code format before redeeming (e.g. length/charset) to fail fast.
if (!loginCode || loginCode.length < 8) {
dispatchToastMessage({ type: 'error', message: 'Invalid or expired login code' });
router.navigate('/login', { replace: true });
return;
} Type guard
const hasRedeemResponse = (r: unknown): r is { loginToken: string; userId: string } =>
typeof r === 'object' && r !== null &&
typeof (r as any).loginToken === 'string' && (r as any).loginToken.length > 0 &&
typeof (r as any).userId === 'string' && (r as any).userId.length > 0; Try / catch
useMutation({
mutationFn: async (code: string) => {
const res = await redeemLoginCode({ code });
if (!hasRedeemResponse(res)) {
throw new Error('Invalid response from login code redemption');
}
return res;
},
onError: () => {
router.navigate('/login', { replace: true });
},
}); Prevention
- Redeem login codes immediately after generation; they are short-lived and one-time.
- Do not reuse or replay codes across clients.
- On failure, restart the OAuth flow to obtain a fresh code.
When it happens
Trigger: loginCode.redeem returns success with a missing/null loginToken or userId; the code was already consumed or expired and the server responded with an incomplete body; malformed OAuth callback integration returning an unexpected shape.
Common situations: Deep-link login (mobile/desktop) where the one-time code expired between issuance and redemption; OAuth provider misconfiguration; replay of an already-used login code.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/495dd2ed77df0aff.
Report an issue: GitHub.