Mintplex-Labs/anything-llm · error · Error

Invalid token.

Error message

Invalid token.

What it means

Thrown by TemporaryAuthToken.validate when prisma.temporary_auth_tokens.findUnique returns null for the supplied token. Tokens are single-use: the finally block (line 98-99) deletes the row after retrieval, so a previously consumed token no longer exists. This also covers tokens that were never issued or were typed incorrectly.

Source

Thrown at server/models/temporaryAuthToken.js:82

   * Validates a temporary auth token and returns the session token
   * 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

  1. Issue a fresh token via TemporaryAuthToken.issue(userId) and generate a new SSO link.
  2. Ensure the SSO flow consumes the token exactly once and redirects away from the token URL immediately.
  3. Confirm the request hits the same instance/database that issued the token.
Defensive patterns

Strategy: fallback

Try / catch

const { sessionToken, error } = await TemporaryAuthToken.validate(token);
if (error === 'Invalid token.') {
  // prompt the user to request a fresh SSO link
}

Prevention

When it happens

Trigger: GET /request-token/sso/simple?token=<X> where X has already been used once, was never created in the DB, or contains a typo/extra whitespace.

Common situations: User clicks an SSO link twice (second click reuses a consumed token). User refreshes the login page that carries the token. Link was generated for a different instance/database. Clock-skewed or restored DB snapshot missing the row.

Understand the failure class

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@526360e320 (2026-08-13). Data as JSON: /api/errors/37c1e322b060a5f4. Report an issue: GitHub.