calcom/cal.diy · error · Error
Invalid refreshed tokens were returned
Error message
Invalid refreshed tokens were returned
What it means
Thrown by parseRefreshTokenResponse when the refreshed token object fails its Zod schema validation. In credential-sync mode it validates against minimumTokenResponseSchema (requires access_token plus at least one numeric expiry-ish field); otherwise against the app-specific schema passed in. A failure means the provider (or sync server) returned a shape that does not match the expected token contract.
Source
Thrown at packages/app-store/_utils/oauth/parseRefreshTokenResponse.ts:36
});
export type ParseRefreshTokenResponse<S extends z.ZodTypeAny> =
| z.infer<S>
| z.infer<typeof minimumTokenResponseSchema>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const parseRefreshTokenResponse = (response: any, schema: z.ZodTypeAny) => {
let refreshTokenResponse;
const credentialSyncingEnabled =
APP_CREDENTIAL_SHARING_ENABLED && process.env.CALCOM_CREDENTIAL_SYNC_ENDPOINT;
if (APP_CREDENTIAL_SHARING_ENABLED && process.env.CALCOM_CREDENTIAL_SYNC_ENDPOINT) {
refreshTokenResponse = minimumTokenResponseSchema.safeParse(response);
} else {
refreshTokenResponse = schema.safeParse(response);
}
if (!refreshTokenResponse.success) {
throw new Error("Invalid refreshed tokens were returned");
}
if (!refreshTokenResponse.data.refresh_token && credentialSyncingEnabled) {
refreshTokenResponse.data.refresh_token = "refresh_token";
}
return refreshTokenResponse.data;
};
export default parseRefreshTokenResponse;
View on GitHub (pinned to 176037d0af)
Solutions
- Log the raw response and the Zod issues (the caller already logs oauth2response/issues) to see which field failed.
- If the provider changed its token shape, update the app's token schema accordingly.
- Ensure the credential-sync server returns at least access_token and a numeric expiry field.
- Confirm the refresh succeeded (a 401/invalid_grant error body parsed as a token will fail validation).
Example fix
// before - schema rejects provider response that uses 'expires_at' string
const schema = z.object({ access_token: z.string(), expires_in: z.number() });
// after - accept the provider's actual shape
const schema = z.object({
access_token: z.string(),
expires_in: z.number().optional(),
expires_at: z.string().optional(),
}); Defensive patterns
Strategy: try-catch
Validate before calling
const refreshTokenResponse = schema.safeParse(response);
if (!refreshTokenResponse.success) {
// log issues before throwing so the cause is diagnosable
console.error('Token schema failure', refreshTokenResponse.error.issues, response);
} Type guard
function isValidTokenResponse<T extends z.ZodTypeAny>(resp: unknown, schema: T): resp is z.infer<T> {
return schema.safeParse(resp).success;
} Try / catch
try {
return parseRefreshTokenResponse(response, schema);
} catch (e) {
// re-fetch or invalidate the token object; surface a reconnect prompt to the user
throw new Error('OAuth token refresh returned an invalid shape; re-authorization may be required.');
} Prevention
- Log the raw refresh response and Zod issues to pinpoint the missing field.
- Keep the app's token schema aligned with the provider's actual response shape.
- Ensure the credential-sync server returns access_token plus a numeric expiry field.
When it happens
Trigger: The token-refresh response is missing access_token, missing any numeric expiry field (in sync mode), or does not match the app's specific token schema (e.g. missing expires_in/refresh_token that the app requires). Happens when the provider changes its token format, returns an error body shaped like a token, or the sync server returns a partial payload.
Common situations: See trigger scenarios.
Related errors
- Could not refresh the token due to connection issue with the
- Unhandled values
- Unable to generate token
- Invalid conferencing app, available apps are:
- OAuth client with ID '${clientId}' not found
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/969ced68f871f2c2.
Report an issue: GitHub.