Mintplex-Labs/anything-llm · error · Error
Token expired.
Error message
Token expired.
What it means
Thrown by TemporaryAuthToken.validate when token.expiresAt < new Date(). Tokens are created with a fixed lifetime (this.expiry). The finally block still deletes the token afterward, so an expired token is also consumed by the failed attempt.
Source
Thrown at server/models/temporaryAuthToken.js:83
* to be set in the browser localStorage for authentication.
* @param {string} publicToken - the token to validate against
* @returns {Promise<{sessionToken: string|null, token: import("@prisma/client").temporary_auth_tokens & {user: import("@prisma/client").users} | null, error: string | null}>}
*/
validate: async function (publicToken = "") {
/** @type {import("@prisma/client").temporary_auth_tokens & {user: import("@prisma/client").users} | undefined | null} **/
let token;
try {
if (!publicToken)
throw new Error(
"Public token is required to validate a temporary auth token."
);
token = await prisma.temporary_auth_tokens.findUnique({
where: { token: String(publicToken) },
include: { user: true },
});
if (!token) throw new Error("Invalid token.");
if (token.expiresAt < new Date()) throw new Error("Token expired.");
if (token.user.suspended) throw new Error("User account suspended.");
// Create a new session token for the user valid for 30 days
const sessionToken = makeJWT(
{ id: token.user.id, username: token.user.username },
process.env.JWT_EXPIRY
);
return { sessionToken, token, error: null };
} catch (error) {
console.error("FAILED TO VALIDATE TEMPORARY AUTH TOKEN.", error.message);
return { sessionToken: null, token: null, error: error.message };
} finally {
// Delete the token after it has been used under all circumstances if it was retrieved
if (token)
await prisma.temporary_auth_tokens.delete({ where: { id: token.id } });
}
},View on GitHub (pinned to 526360e320)
Solutions
- Issue a new token; the old one is now deleted and cannot be reused.
- If the window is too short for your workflow, increase TemporaryAuthToken.expiry to a larger value (e.g. 1000*60*60 for one hour) and fix the misleading comment.
- Deliver SSO links through a channel the user will act on promptly.
Example fix
// before (expiry is ~6 minutes despite the comment) expiry: 1000 * 60 * 6, // 1 hour // after expiry: 1000 * 60 * 60, // 1 hour
Defensive patterns
Strategy: retry
Try / catch
const { error } = await TemporaryAuthToken.validate(token);
if (error === 'Token expired.') {
const { token: fresh } = await TemporaryAuthToken.issue(userId);
// send a new link
} Prevention
- Deliver SSO links through a channel the user checks immediately.
- If the default 6-minute window is too short, raise TemporaryAuthToken.expiry and correct the misleading '1 hour' comment.
- Discard expired links rather than retrying them.
When it happens
Trigger: GET /request-token/sso/simple?token=<X> where more than the configured expiry window has elapsed since TemporaryAuthToken.issue created the row.
Common situations: The SSO link sat in an email/chat for too long before the user clicked it. The user's device was offline. Note: the source comment says '1 hour' but this.expiry is 1000*60*6 (6 minutes) — treat the effective window as ~6 minutes unless the constant is corrected.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Public token is required to validate a temporary auth token.
- Invalid token.
- res.statusText || "Error generating api key."
- Community Hub connection key not found
- An error occurred while downloading the model
AI-assisted analysis of Mintplex-Labs/anything-llm@526360e320 (2026-08-13).
Data as JSON: /api/errors/8e8bf68293124c01.
Report an issue: GitHub.