slymnoyann/hey-1 · critical · Error
Missing tokens in refresh response
Error message
Missing tokens in refresh response
What it means
Thrown when the refresh mutation does return an AuthenticationTokens payload, but either accessToken or refreshToken within it is empty/undefined. The server acknowledged the refresh request and typed the response as tokens, yet the actual credentials are missing, so signIn cannot be performed safely.
Source
Thrown at src/helpers/tokenManager.ts:29
try {
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
const { data } = await apolloClient.mutate<RefreshMutation>({
mutation: RefreshDocument,
variables: { request: { refreshToken } }
});
const refreshResult = data?.refresh;
if (!refreshResult) {
throw new Error("No response from refresh");
}
if (refreshResult.__typename === "AuthenticationTokens") {
const { accessToken: newAccessToken, refreshToken: newRefreshToken } =
refreshResult;
if (!newAccessToken || !newRefreshToken) {
throw new Error("Missing tokens in refresh response");
}
signIn({
accessToken: newAccessToken,
refreshToken: newRefreshToken
});
return newAccessToken;
}
if (refreshResult.__typename === "ForbiddenError") {
signOut();
throw new Error("Refresh token is invalid or expired");
}
if (attempt < MAX_RETRIES - 1) {
await new Promise((resolve) =>
setTimeout(resolve, 2 ** attempt * 1000)View on GitHub (pinned to 88c8f9d553)
Solutions
- Inspect the raw refresh response in the network tab to confirm which token field is missing
- Align the client mutation selection set with the current API schema (both accessToken and refreshToken selected)
- If the server is yours, fix the resolver to always return both tokens or return an error typename instead
- Treat this as a hard auth failure: signOut() before throwing so the user is not stuck in a broken session
Example fix
// before
if (!newAccessToken || !newRefreshToken) {
throw new Error("Missing tokens in refresh response");
}
// after
if (!newAccessToken || !newRefreshToken) {
signOut();
throw new Error("Missing tokens in refresh response");
} Defensive patterns
Strategy: type-guard
Validate before calling
// nothing caller-side can validate pre-flight beyond having a well-formed refresh token if (!refreshToken) signOut();
Type guard
const isCompleteTokens = (r: unknown): r is { __typename: "AuthenticationTokens"; accessToken: string; refreshToken: string } =>
typeof r === "object" && r !== null &&
r.__typename === "AuthenticationTokens" &&
typeof (r as { accessToken?: unknown }).accessToken === "string" &&
typeof (r as { refreshToken?: unknown }).refreshToken === "string"; Try / catch
try {
await refreshTokens(refreshToken);
} catch (e) {
if (e instanceof Error && e.message === "Missing tokens in refresh response") {
signOut();
window.location.href = "/login";
}
throw e;
} Prevention
- Keep the client mutation selection set in sync with the API schema
- Sign out on this specific error to avoid a half-authenticated session
- Contract-test the refresh mutation response shape in CI
When it happens
Trigger: API returns { __typename: 'AuthenticationTokens', accessToken: null } or omits refreshToken; a schema change making one token field nullable; or a partially successful server-side session regeneration where one token fails to mint.
Common situations: Backend version mismatch after a deploy that altered the refresh response shape, server-side JWT signing failure producing null fields, or a mocked/test server returning an incomplete AuthenticationTokens object.
Related errors
- No response from refresh
- Refresh token is invalid or expired
- Unknown error during token refresh
- uploadFileToIPFS failed
- Failed to upload file
AI-assisted analysis of slymnoyann/hey-1@88c8f9d553 (2026-08-28).
Data as JSON: /api/errors/54197226afa0c029.
Report an issue: GitHub.