Mintplex-Labs/anything-llm · warning

Invalid password.

Error message

Invalid password.

What it means

Message 'Invalid password.' from POST /system/reset-password, arriving as HTTP 500 even though it is a client mistake. resetPassword trims the new password and throws when the result is empty; the endpoint's catch block converts any throw into a 500 JSON response carrying the thrown message verbatim.

Source

Thrown at server/endpoints/system.js:438

    "/system/reset-password",
    [isMultiUserSetup],
    async (request, response) => {
      try {
        const { token, newPassword, confirmPassword } = reqBody(request);
        const { success, message, error } = await resetPassword(
          token,
          newPassword,
          confirmPassword
        );

        if (success) {
          response.status(200).json({ success, message });
        } else {
          response.status(400).json({ success, error });
        }
      } catch (error) {
        console.error("Error resetting password:", error);
        response.status(500).json({ success: false, message: error.message });
      }
    }
  );

  app.get(
    "/system/system-vectors",
    [validatedRequest, flexUserRoleValid([ROLES.admin, ROLES.manager])],
    async (request, response) => {
      try {
        const query = queryParams(request);
        const VectorDb = getVectorDbClass();
        const vectorCount = !!query.slug
          ? await VectorDb.namespaceCount(query.slug)
          : await VectorDb.totalVectors();
        response.status(200).json({ vectorCount });
      } catch (e) {
        console.error(e.message, e);
        response.sendStatus(500).end();

View on GitHub (pinned to 20f6d3546c)

Solutions

  1. Send a non-empty newPassword after trimming
  2. Note the follow-on rule: the password must also pass the joi-password-complexity check inside User.update (min 8 chars by default, tunable via PASSWORDMINCHAR) or you will get a 400 with that message instead
  3. In clients, treat a 500 from this endpoint carefully — real server faults and this client error share the status code; branch on the message

Example fix

// before
await api.post('/system/reset-password', {
  token, newPassword: '   ', confirmPassword: '   '
}); // 500 { success:false, message:'Invalid password.' }

// after
await api.post('/system/reset-password', {
  token, newPassword: 'correct horse battery', confirmPassword: 'correct horse battery'
});
Defensive patterns

Strategy: validation

Validate before calling

// Trim and require a non-empty password before calling the API
const newPassword = String(rawNewPassword ?? '').trim();
if (!newPassword) throw new Error('New password is required');
await api.post('/system/reset-password', { token, newPassword, confirmPassword: newPassword });

Type guard

function isNonEmptyPassword(v) {
  return typeof v === 'string' && v.trim().length > 0;
}

Prevention

When it happens

Trigger: POST /system/reset-password with newPassword omitted, empty, or whitespace-only (e.g. " ") while holding a valid reset token. The empty-check runs before the confirm-password comparison, so confirmPassword is irrelevant here.

Common situations: Form submitted before the new-password field was filled; whitespace-only paste; automated tests sending empty strings and misreading the 500 as a server fault.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@20f6d3546c (2026-08-18). Data as JSON: /api/errors/1b2bde00c08dcb4f. Report an issue: GitHub.